Sql server 使用动态透视查询时多次指定该列?
假设我有两个表,Sql server 使用动态透视查询时多次指定该列?,sql-server,pivot,Sql Server,Pivot,假设我有两个表,table1和table2,我想用cte视图uvw\u TestView来透视它们 表1 id1 | name | locationCode ----|------|----------------- 1 | a | 3 2 | b | 1 3 | c | 2 表2 id2 | id1 | StudyName | dateStudy ----|-----|-----------|------ 1 | 1 | Math | 2015
table1
和table2
,我想用cte视图uvw\u TestView
来透视它们
表1
id1 | name | locationCode
----|------|-----------------
1 | a | 3
2 | b | 1
3 | c | 2
表2
id2 | id1 | StudyName | dateStudy
----|-----|-----------|------
1 | 1 | Math | 2015-05-23
2 | 1 | Chemistry | 2015-06-20
3 | 2 | Math | 2016-09-02
4 | 3 | Physics | 2016-12-26
5 | 2 | Chemistry | 2017-01-05
6 | 2 | Math | 2017-06-06
7 | 3 | Chemistry | 2018-02-22
这里的视图只是一个从表1
学习的地方
如果将日期从2015-05-01
过滤到2017-01-01
id1 | name | Math | Chemistry | Physics
1 | a | 2015-05-23 | 2015-06-20 | ---
2 | b | 2016-09-02 | --- | ---
3 | c | --- | --- | 2016-12-26
很抱歉,我不能在这里显示真正的查询,但我尝试将其与之类似
我尝试在没有日期筛选器的情况下使用此查询
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX), @dtDate1 DATETIME, @dtDate2 DATETIME;
SET @dtDate1 = '2015-05-01'
SET @dtDate2 = '2017-01-01'
SET @columns = N'';
SELECT @columns += N', ' + QUOTENAME(StudyName)
FROM (SELECT DISTINCT t2.StudyName FROM dbo.table2 AS t2) AS x;
SET @sql = N'
WITH cte AS
(
SELECT * FROM dbo.uvw_TestView WHERE idView = '001'
UNION ALL
SELECT a.* FROM dbo.uvw_TestView a INNER JOIN cte b ON a.ParentID = b.idView
SELECT * FROM
(SELECT DISTINCT * FROM cte) ct
INNER JOIN (
SELECT p.*, ' + STUFF(@columns, 1, 2, '') + '
FROM
(
SELECT DISTINCT
tb1.id1,
tb1.name,
tb2.dateStudy,
tb2.StudyName
FROM dbo.table1 AS tb1
INNER JOIN dbo.table2 tb2 tb2
ON tb1.id1 = tb2.id1
) AS j
PIVOT
(
MIN(dateStudy) FOR StudyName IN ('
+ STUFF(REPLACE(@columns, ', [', ',['), 1, 1, '')
+ ')
) AS p) tbl ON tbl.id1 = ct.id1';
PRINT @sql;
EXEC sp_executesql @sql;
SELECT @columns += N', ' + QUOTENAME(StudyName)
FROM (SELECT DISTINCT t2.StudyName FROM dbo.table2 AS t2) AS x;
SET @sql = N'
WITH cte AS
(
SELECT * FROM dbo.uvw_TestView WHERE idView = '001'
UNION ALL
SELECT a.* FROM dbo.uvw_TestView a INNER JOIN cte b ON a.ParentID = b.idView
SELECT * FROM
(SELECT DISTINCT * FROM cte) ct
INNER JOIN (
SELECT p.*, ' + STUFF(@columns, 1, 2, '') + '
FROM
(
SELECT DISTINCT
tb1.id1,
tb1.name,
tb2.dateStudy,
tb2.StudyName
FROM dbo.table1 AS tb1
INNER JOIN dbo.table2 tb2 tb2
ON tb1.id1 = tb2.id1
) AS j
PIVOT
(
MIN(dateStudy) FOR StudyName IN ('
+ STUFF(REPLACE(@columns, ', [', ',['), 1, 1, '')
+ ')
) AS p) tbl ON tbl.id1 = ct.id1 where tbl.dateStudy BETWEEN ''' + @dtDate1 +''' AND ''' + @dtDate2;
但是获取错误列“Math”被多次指定为“tbl”。
我还尝试了日期过滤器
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX), @dtDate1 DATETIME, @dtDate2 DATETIME;
SET @dtDate1 = '2015-05-01'
SET @dtDate2 = '2017-01-01'
SET @columns = N'';
SELECT @columns += N', ' + QUOTENAME(StudyName)
FROM (SELECT DISTINCT t2.StudyName FROM dbo.table2 AS t2) AS x;
SET @sql = N'
WITH cte AS
(
SELECT * FROM dbo.uvw_TestView WHERE idView = '001'
UNION ALL
SELECT a.* FROM dbo.uvw_TestView a INNER JOIN cte b ON a.ParentID = b.idView
SELECT * FROM
(SELECT DISTINCT * FROM cte) ct
INNER JOIN (
SELECT p.*, ' + STUFF(@columns, 1, 2, '') + '
FROM
(
SELECT DISTINCT
tb1.id1,
tb1.name,
tb2.dateStudy,
tb2.StudyName
FROM dbo.table1 AS tb1
INNER JOIN dbo.table2 tb2 tb2
ON tb1.id1 = tb2.id1
) AS j
PIVOT
(
MIN(dateStudy) FOR StudyName IN ('
+ STUFF(REPLACE(@columns, ', [', ',['), 1, 1, '')
+ ')
) AS p) tbl ON tbl.id1 = ct.id1';
PRINT @sql;
EXEC sp_executesql @sql;
SELECT @columns += N', ' + QUOTENAME(StudyName)
FROM (SELECT DISTINCT t2.StudyName FROM dbo.table2 AS t2) AS x;
SET @sql = N'
WITH cte AS
(
SELECT * FROM dbo.uvw_TestView WHERE idView = '001'
UNION ALL
SELECT a.* FROM dbo.uvw_TestView a INNER JOIN cte b ON a.ParentID = b.idView
SELECT * FROM
(SELECT DISTINCT * FROM cte) ct
INNER JOIN (
SELECT p.*, ' + STUFF(@columns, 1, 2, '') + '
FROM
(
SELECT DISTINCT
tb1.id1,
tb1.name,
tb2.dateStudy,
tb2.StudyName
FROM dbo.table1 AS tb1
INNER JOIN dbo.table2 tb2 tb2
ON tb1.id1 = tb2.id1
) AS j
PIVOT
(
MIN(dateStudy) FOR StudyName IN ('
+ STUFF(REPLACE(@columns, ', [', ',['), 1, 1, '')
+ ')
) AS p) tbl ON tbl.id1 = ct.id1 where tbl.dateStudy BETWEEN ''' + @dtDate1 +''' AND ''' + @dtDate2;
并获取错误字符串或二进制数据将被截断。
那么,我如何解决这个错误以获得结果呢?我看到您有一个
PRINT@sql代码>语句。但是你看了这个问题了吗
错误为“tbl”多次指定了列“Math”。
是由于此行引起的
SELECT p.*, ' + STUFF(@columns, 1, 2, '') + '
您的列
将包含列列表,如[化学],[数学]
和p.*
实际上包含透视
结果中的所有列。所以这些轴列是重复的
你只需做一个选择*
,就足够了 您打印了正在执行的sql,但没有将其包含在帖子中?我看不出确切的问题,但几乎可以肯定是您使用SELECT*
造成的。如果对联接执行选择*
,则如果两个(或多个)表碰巧有一个或多个同名列,则会看到当前的错误消息。要解决此问题,请明确列出所需的列,并使用同名别名列。哦,这就是我的列重复的原因,谢谢,这很有用