T-SQL查询: PIVOT/UNPIVOT 逻辑操作步骤

--【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

*/





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值