2012-12-13 53 views
4

我有一個3列的表:ItemCode,Quantity和DocDate。 我想在一個更「優雅」的方式來創建以下報告:SQL按年份報告,尋找一個優雅的解決方案

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) 

我敢肯定有寫這更好的,更有效的方式,但我不能想出正確的語法。有任何想法嗎?

回答

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 
5

這種類型的數據轉換被稱爲一個PIVOT。有幾種方法可以執行此操作。您可以使用PIVOT功能,也可以使用聚合函數與CASE聲明:

靜態樞軸版本:這是你硬編碼的所有值到查詢

select ItemCode, [2011], [2012] 
from 
(
    SELECT ItemCode, 
    QUANTITY, 
    YEAR(DocDate) Year 
    FROM MyTable 
) src 
pivot 
(
    sum(quantity) 
    for year in ([2011], [2012]) 
) piv 

SQL Fiddle with Demo

案例與總結:

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; 

SQL Fiddle with Demo

動態透視:前兩個版本將工作的偉大是你有一個已知數量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) 

SQL Fiddle with Demo

所有三個版本都會產生相同的結果:

| ITEMCODE | 2011 | 2012 | 
-------------------------- 
|  1 | 200 | 45 | 
|  2 | 89 | 0 | 
|  3 | 0 | 7 |