Dynamic Pivot SQL Server中的多个列

时间:2017-07-31 17:20:07

标签: sql-server

我有一张这样的表

--index-info

我在SQL Server中使用动态数据透视表寻找以下输出

Id   Name   FromAddress   ToAddress
1    Joey      ABC          JKL
2    Joey      DEF          MNP
3    Joey      GHI          OQR

注意:行数会根据Id值更改,因此我尝试使用动态Pivot获取输出。

这是我尝试的代码,看起来它是正确的,但是给我一个错误。

Name   FromAdrs1   FromAdrs2   FromAdrs3   ToAdrs1   ToAdrs2   ToAdrs3
Joey     ABC         DEF         GHI          JKL      MNP       OQR

感谢任何帮助。谢谢大家的时间。

编辑:这是错误

enter image description here

2 个答案:

答案 0 :(得分:1)

我认为问题是IN ()中的PIVOT表达式。列列表显式必须是字段名称列表,而不是函数,而不是varchar文字或函数值列表。你在那里有一个REPLACE()功能。引擎期望找到一个名为[REPLACE]的字段,然后被显示的空括号弄糊涂。

这是有效的(强调方括号):

SELECT VendorID, Employee, Orders
FROM 
   (SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
   FROM pvt) p
UNPIVOT
   (Orders FOR Employee IN 
      ([Emp1], [Emp2], [Emp3], [Emp4], [Emp5])
)AS unpvt;

这不是:

SELECT VendorID, Employee, Orders
FROM 
   (SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
   FROM pvt) p
UNPIVOT
   (Orders FOR Employee IN 
      ('Emp1', 'Emp2', 'Emp3', 'Emp4', 'Emp5')
)AS unpvt;

这是无效的:

SELECT VendorID, Employee, Orders
FROM 
   (SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
   FROM pvt) p
UNPIVOT
   (Orders FOR Employee IN 
      (REPLACE('Emp1','1','A'), REPLACE('Emp2','2','B'))
)AS unpvt;

execute(@query)替换为select @queryprint @query,以查看代码生成的查询,并以此方式对查询分析器中的语法进行故障排除。然后倒退。

您希望在构建查询的同一级别执行REPLACE()。最终在@query变量中的查询应该已经修改了列名。

或者,您可以生成@colsFromLabels@colsToLabels@colsFrom@colsTo,其中前两个添加了'from'to位而后两者只是列名。

对于方括号逃脱,你想要的输出有点粗略。

答案 1 :(得分:0)

好吧,我创建了一个临时表来进行一些测试。该解决方案首先需要一个univot。我建议使用/不使用额外的测试数据运行,以了解围绕此解决方案的其他一些行为 - MAX聚合带来的奇怪现象以及更改“名称”中的值时可能缺少的新行

GL。希望它有所帮助。

-------------------------
-- Some test data here
CREATE table #addresses ( Id int, Name varchar(5), FromAddress varchar(5), ToAddress varchar(5))
insert into #addresses(id, Name, FromAddress, ToAddress) Values
(1,'Joey', 'ABC', 'JKL')
, (2,'Joey', 'DEF', 'MNO')
, (3,'Joey', 'GHI', 'PQR')
, (4,'Spike', 'XXX', 'YYY')
, (1,'Spike', 'QQQ', 'RRR')

-------------------------
--  Solution starts here.  create a temp table and unpivot your data into it.
--  Your initial technique of does not work, PIVOT only supports one aggregation

CREATE table #unpvt(RowColCode varchar(20), vals varchar(20))
Insert into #unpvt
SELECT ColCode + '_' + Cast(ID as varchar(2)) as RowColCode, vals
FROM #addresses a
UNPIVOT
    (vals for ColCode in (Name,FromAddress,ToAddress)) c

-------------------------
--  Read the temp table for a column list

declare @ColList nvarchar(max)
set @ColList = STUFF((
    SELECT distinct ',[' + t.RowColCode + ']'
            FROM #unpvt t
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)'),1,1,'')


-------------------------
-- 're pivot' the data using your new column list

declare @qry varchar(max)
set @qry = '

select *
from
    #unpvt
    PIVOT(
    MAX(vals)
    FOR RowColCode in (' +@ColList +  ') 
    ) rslt
'


execute(@qry)