我有一个包含3列的表:ItemCode,Quantity和DocDate。 我想以更“优雅”的方式创建以下报告:
SELECT T0.ItemCode,
(SELECT SUM(QUANTITY) FROM MyTable T1 WHERE YEAR(T0.DocDate) = 2011 AND T0.ItemCode = T1.ItemCode) AS '2011',
(SELECT SUM(QUANTITY) FROM MyTable T1 WHERE YEAR(T0.DocDate) = 2012 AND T0.ItemCode = T1.ItemCode) AS '2012'
FROM MyTable T0
GROUP BY T0.ItemCode, YEAR(T0.DocDate)
我很确定有更好,更有效的方式来编写这个但我无法提出正确的语法。有什么想法吗?
答案 0 :(得分:5)
你可以试试这个:
SELECT T0.ItemCode,
SUM(CASE WHEN YEAR(T0.DocDate) = 2011 THEN QUANTITY ELSE 0 END) AS '2011',
SUM(CASE WHEN YEAR(T0.DocDate) = 2012 THEN QUANTITY ELSE 0 END) AS '2012'
FROM MyTable T0
GROUP BY
T0.ItemCode
答案 1 :(得分:5)
此类数据转换称为PIVOT
。有几种方法可以执行此操作。您可以使用PIVOT
函数,也可以使用带有CASE
语句的聚合函数:
Static Pivot版本:这是您将所有值硬编码到查询中的地方
select ItemCode, [2011], [2012]
from
(
SELECT ItemCode,
QUANTITY,
YEAR(DocDate) Year
FROM MyTable
) src
pivot
(
sum(quantity)
for year in ([2011], [2012])
) piv
汇总案例:
SELECT ItemCode,
SUM(CASE WHEN YEAR(DocDate) = 2011 THEN QUANTITY ELSE 0 END) AS '2011',
SUM(CASE WHEN YEAR(DocDate) = 2012 THEN QUANTITY ELSE 0 END) AS '2012'
FROM MyTable
GROUP BY ItemCode;
动态数据透视:以前的两个版本效果很好,您可以使用已知数量的year
值进行转换,但是您有一个未知数,那么您可以使用动态sql:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(YEAR(DocDate))
from mytable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT itemcode, ' + @cols + ' from
(
select itemcode, quantity, year(docdate) year
from mytable
) x
pivot
(
sum(quantity)
for year in (' + @cols + ')
) p '
execute(@query)
所有三个版本都会产生相同的结果:
| ITEMCODE | 2011 | 2012 |
--------------------------
| 1 | 200 | 45 |
| 2 | 89 | 0 |
| 3 | 0 | 7 |