2012-02-13 71 views
4

我試圖改變這樣的數據:PIVOT SQL數據和填寫空白

ItemID MonthAsInt Month  Year InvType  Quantity 
4643 4   April  2011 Shipment 10 
4643 5   May  2011 Shipment 10 
4643 7   July  2011 Shipment 10 
4643 8   August 2011 Destroy  10 
4643 11   November 2011 Shipment 25 
4643 12   December 2011 Picking  1 

進入這個(基本上,12個月的快照):

   February March April  May June July August ... 

Shipment  0   0  10  10  0  10  0 
Picking  0   0  0   0  0  0  0 
Destroy  ... 

我已經搞砸PIVIOT方法,但我沒有太多運氣。在這一點上,我只有我GETDATE()GETDATE() - 12 months之間需要日期的列表(與下面的查詢檢索):

DECLARE @BeginDate DATETIME 
DECLARE @EndDate DATETIME 

SET @BeginDate = GETDATE(); 
SET @EndDate = DATEADD(MONTH, -12, GETDATE()); 

WITH CTE_DatesTable 
AS 
(
    SELECT @EndDate AS [Date] 

    UNION ALL 

    SELECT DATEADD(dd, 1, [date]) 
    FROM CTE_DatesTable 
    WHERE DATEADD(dd, 1, [date]) <= @BeginDate 
) 

SELECT DISTINCT DATENAME(MONTH, [date]) + ' ' 
     + CAST(YEAR([date]) AS VARCHAR(4)) AS MonthYear, 
       YEAR([date]) AS YearAsInt, 
       MONTH([Date]) AS MonthAsInt 
FROM   CTE_DatesTable 
ORDER BY  YEAR([date]), MONTH([Date]) 
OPTION   (MAXRECURSION 0) 

看到查詢在行動here

我試圖完成什麼?我正朝着正確的方向走嗎?任何幫助,將不勝感激!

+1

什麼也沒有用PIVOT工作? – 2012-02-13 18:17:27

+0

@ subt13,** Me **。我從來沒有用過它,我不知道如何「填補空白」。例如,我需要爲所有未包含在第一個結果集中的月份顯示零。 – 2012-02-13 18:21:30

+0

使用樞軸,就是這麼做的。你可以使用isnull(...,0) – 2012-02-13 18:26:48

回答

2

你可以做到這一點沒有樞軸(我覺得令人畏懼的語法)。由於事先不知道列的實際佈局,我認爲這對於動態SQL來說是最簡單的。如下表/樣本數據:

USE tempdb; 
GO 

CREATE TABLE dbo.foo 
(
    ItemID INT, 
    MonthAsInt INT, 
    [Month] VARCHAR(12), 
    [Year] INT, 
    InvType VARCHAR(12), 
    Quantity INT 
); 

INSERT dbo.foo SELECT 4643,4 ,'April ',2011,'Shipment',10 
UNION ALL SELECT 4643,5 ,'May  ',2011,'Shipment',10 
UNION ALL SELECT 4643,7 ,'July ',2011,'Shipment',10 
UNION ALL SELECT 4643,8 ,'August ',2011,'Destroy ',10 
UNION ALL SELECT 4643,11,'November',2011,'Shipment',25 
UNION ALL SELECT 4643,12,'December',2011,'Picking ',1; 

您可以使用一個簡單得多的CTE產生個月的清單,並建立基於關閉的一個動態SQL語句:

DECLARE @sql NVARCHAR(MAX) = N''; 

;WITH n AS 
(
    SELECT TOP (12) d = DATEADD 
    (
     MONTH, 
     -(ROW_NUMBER() OVER (ORDER BY [object_id]) - 1), 
     GETDATE() 
    ) 
    FROM sys.objects 
    ORDER BY d DESC 
) 
SELECT @sql = @sql + N',' + CHAR(13) + CHAR(10) + DATENAME(MONTH, d) 
    + ' = SUM(CASE WHEN [Year] = ' + CONVERT(VARCHAR(4), DATEPART(YEAR, d)) 
    + ' AND MonthAsInt = ' + CONVERT(VARCHAR(2), DATEPART(MONTH, d)) 
    + ' THEN Quantity ELSE 0 END)' 
FROM n 
ORDER BY d; 

SELECT @sql = N'SELECT InvType' + @sql + ' 
    FROM dbo.foo 
    GROUP BY InvType'; 

PRINT @sql; 
-- EXEC sp_executesql @sql; 

我把PRINT那麼你可以在運行之前進行測試。我不確定您是否需要12個月或13個月,如果您需要13個月,則可以將TOP (12)更改爲TOP (13),或者如果您不希望包含當前月份,請將其刪除-1

+0

你可以用類似的方式用動態SQL建立一個'PIVOT'。您也可以考慮將年份添加到列名中,以便結果明確。最後,輸出SQL沒有'ORDER BY' - 你的意思是'ORDER BY InvType DESC'還是你不關心命令? – 2012-02-13 18:51:28

+0

完美的作品。我以前從未使用過動態SQL。這是爲什麼我需要更多地考慮它的一個很好的例子。謝謝你的幫助! – 2012-02-13 19:46:38

2

如果你需要一個動態的支點:see here

否則

這是你怎麼做會轉動。當然,PIVOT要求您事先知道您的數據的外觀。如果您需要動態數據透視表,則會有大量人們已經編寫的動態交叉表/數據透視查詢/ sps。

DECLARE @BeginDate DATETIME 
DECLARE @EndDate DATETIME 

SET @BeginDate = GETDATE(); 
SET @EndDate = DATEADD(MONTH, -12, GETDATE()); 

WITH CTE_DatesTable 
AS 
(
    SELECT @EndDate AS [Date] 

    UNION ALL 

    SELECT DATEADD(dd, 1, [date]) 
    FROM CTE_DatesTable 
    WHERE DATEADD(dd, 1, [date]) <= @BeginDate 
) 

    SELECT DISTINCT DATENAME(MONTH, [date]) + ' ' + CAST(YEAR([date]) AS VARCHAR(4)) AS MonthYear, 
        YEAR([date]) AS YearAsInt, 
        MONTH([Date]) AS MonthAsInt, 
        case when month([date]) < 5 then 'Shipment' else 'Picking' end InvType, 
        floor(10 * RAND() * month([date])) Quantity 
    into #orig 
    FROM   CTE_DatesTable 
    ORDER BY  YEAR([date]), MONTH([Date]) 
    OPTION   (MAXRECURSION 0) 

update #orig 
set Quantity = null 
where MonthYear = 'February 2011' 

select * from #orig 

select * 
from 
(
    select isnull(Quantity, 0) Quantity, MonthYear from #orig 
) SourceTbl 
PIVOT 
(
    sum(Quantity) 
    for MonthYear in ([February 2011], [March 2011]) 
) PivotTbl 

drop table #orig 

結果:

February 2011 March 2011 
0     29 
+0

'month when([date])<5'是什麼意思? – 2012-02-13 18:54:46

+0

@AaronBertrand - 添加示例數據。 – 2012-02-13 18:56:36

+0

好的,我陷入了困境。希望OP能夠理解這不是解決方案的一部分。現在,其他10-11個月呢? :-) – 2012-02-13 18:58:54