--【PIVOT】 USE tempdb GO -- DROP TABLE #test CREATE TABLE #test(Empid int,Oderyear varchar(4),val numeric(18,2)) INSERT INTO #test(Empid,Oderyear,val) VALUES (1,'2012',156823), (1,'2013',256833.56), (1,'2014',456823.33), (3,'2014',26536.69), (4,'2012',56823.85), (4,'2013',452365.23), (2,'2014',56213), (3,'2013',456123), (4,'2014',256423.33) SET STATISTICS PROFILE ON --查看执行计划 SELECT * FROM #test PIVOT( MAX(VAL) FOR Oderyear IN([2012],[2013],[2014]) ) AS T /* SELECT * FROM #test PIVOT( MAX(VAL) FOR Oderyear IN([2012],[2013],[2014]) ) AS T |--Stream Aggregate(GROUP BY:([tempdb].[dbo].[#test].[Empid]) DEFINE:( [Expr1004]=MAX(CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2012' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END) [Expr1005]=MAX(CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2013' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END) [Expr1006]=MAX(CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2014' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END)) |--Sort(ORDER BY:([tempdb].[dbo].[#test].[Empid] ASC)) |--Table Scan(OBJECT:([tempdb].[dbo].[#test])) 1. 读取表[#test] 2. 表排序[#test].[Empid] ASC 3. 聚合查询(按查询的步骤执行) 3.1 分组GROUP BY:([tempdb].[dbo].[#test].[Empid]) 3.2 扩展,将IN子句扩展到相应目标列 ,CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2012' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END ,CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2013' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END ,CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2014' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END 3.3 聚合 ,MAX(CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2012' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END) AS [2012] ,MAX(CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2013' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END) AS [2013] ,MAX(CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2014' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END) AS [2014] */ --逻辑上等效如下: SELECT [tempdb].[dbo].[#test].[Empid] ,MAX(CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2012' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END) AS [2012] ,MAX(CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2013' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END) AS [2013] ,MAX(CASE WHEN [tempdb].[dbo].[#test].[Oderyear]='2014' THEN [tempdb].[dbo].[#test].[val] ELSE NULL END) AS [2014] FROM [tempdb].[dbo].[#test] GROUP BY [tempdb].[dbo].[#test].[Empid] /*结果: Empid 2012 2013 2014 ----- ----- -------- -------- 1 156823.00 256833.56 456823.33 2 NULL NULL 56213.00 3 NULL 456123.00 26536.69 4 56823.85 452365.23 256423.33 */
--【UNPIVOT】 -- DROP TABLE #test2 SELECT * INTO #test2 FROM #test PIVOT( MAX(VAL) FOR Oderyear IN([2012],[2013],[2014]) ) AS T --以刚才的结果为例 SELECT Empid,Oderyear,val FROM #test2 UNPIVOT( VAL FOR Oderyear IN([2012],[2013],[2014]) ) AS T /*执行计划: SELECT Empid,Oderyear,val FROM #test2 UNPIVOT( VAL FOR Oderyear IN([2012],[2013],[2014]) ) AS T |--Filter(WHERE:([Expr1008] IS NOT NULL)) |--Nested Loops(Left Outer Join, OUTER REFERENCES:( [tempdb].[dbo].[#test2].[2012],[tempdb].[dbo].[#test2].[2013],[tempdb].[dbo].[#test2].[2014])) |--Compute Scalar(DEFINE:([Expr1004]=[tempdb].[dbo].[#test2].[Empid])) | |--Table Scan(OBJECT:([tempdb].[dbo].[#test2])) |--Constant Scan(VALUES:( (N'2012',[tempdb].[dbo].[#test2].[2012]),(N'2013',[tempdb].[dbo].[#test2].[2013]),(N'2014',[tempdb].[dbo].[#test2].[2014]))) 1. 读取表[#test2] 2. 嵌套连接[Empid]与 (N'2012',[tempdb].[dbo].[#test2].[2012]), (N'2013',[tempdb].[dbo].[#test2].[2013]), (N'2014',[tempdb].[dbo].[#test2].[2014]) 生成3个副本,IN子句有几个列就生成几个副本 结果: Empid 2012 2013 2014 Oderyear ----- ----- -------- -------- ---- 1 156823.00 256833.56 456823.33 2012 1 156823.00 256833.56 456823.33 2013 1 156823.00 256833.56 456823.33 2014 2 NULL NULL 56213.00 2012 2 NULL NULL 56213.00 2013 2 NULL NULL 56213.00 2014 3 NULL 456123.00 26536.69 2012 3 NULL 456123.00 26536.69 2013 3 NULL 456123.00 26536.69 2014 4 56823.85 452365.23 256423.33 2012 4 56823.85 452365.23 256423.33 2013 4 56823.85 452365.23 256423.33 2014 3. 提取元素,VAL FOR Oderyear 中保留对应的值 结果: Empid VAL Oderyear ----- ----- -------- 1 156823.00 2012 1 256833.56 2013 1 456823.33 2014 2 NULL 2012 2 NULL 2013 2 56213.00 2014 3 NULL 2012 3 456123.00 2013 3 26536.69 2014 4 56823.85 2012 4 452365.23 2013 4 256423.33 2014 4. 过滤空值行Filter(WHERE:([Expr1008] IS NOT NULL) 结果: Empid VAL Oderyear ----- ----- -------- 1 156823.00 2012 1 256833.56 2013 1 456823.33 2014 2 56213.00 2014 3 456123.00 2013 3 26536.69 2014 4 56823.85 2012 4 452365.23 2013 4 256423.33 2014 */