2016-07-13 97 views
1

我試圖通過SQL查詢&數據透視表創建滾動的12個月銷售歷史記錄。我們使用的程序(SAP B1)只有一個簡單的SQL編輯器,所以我希望能夠完成下面的內容。我環顧四周,發現了我們的系統似乎並不太喜歡的各種動態SQL查詢。我主要想的東西來代替像月月 (GETDATE())具有移動月的動態SQL數據透視表

SELECT * 
FROM 
(
    SELECT T0.ItemCode,SUM(T0.Quantity) AS Quantity, T0.WhsCode AS 'Warehouse',CONVERT(varchar,datepart(MONTH,t1.docdate)) PERIOD 
    FROM INV1 T0 
    INNER JOIN OINV T1 on T0.DocEntry = T1.DocEntry 
    WHERE T1.Canceled = 'N' 
    AND T0.ItemCode = '75910' AND DATEDIFF(m, T0.DocDate,getdate()) < 12 
    GROUP BY T0.ItemCode, T0.WhsCode,CONVERT(varchar,datepart(YEAR,T1.DocDate)) ,CONVERT(varchar,datepart(MONTH,T1.DocDate)) 
    ) S 
PIVOT (SUM(QUANTITY) FOR [PERIOD] IN 
([7],[6],[5],[4],[3],[2],[1],[12],[11],[10],[9],[8])) P 

時期只是返回DocDate月份的查詢。然後數據透視歷年(7 = 7月,6 = 6月等)。因此,當前月份排在第一位。 我希望底部是沿着下面的線,但它不工作。

(Month(GetDate()),Month(GetDate())-1,Month(GetDate())-2 etc.)) P 

得到 「7」, 「6」 右後衛8

我希望是有道理的。有類似的可能嗎?還是必須通過更高級的動態查詢來完成?

這是我期待的回報,但隨着期間在底部更新時,一個新月開始。 enter image description here

+1

不能產生的月名稱的列名而不使用動態查詢。你可以自己按順序生成數字(例如,通過將PERIOD改爲類似於(12 + datepart(month,getdate()))的方式(例如FOR [PERIOD] IN([1],[2] ...] datepart(month,mydate))%12 + 1',其中[1]將是當前月份,[2]前一個月等)但是要生成實際的月份名稱必須使用動態SQL – ZLK

+0

聽起來就像它可以工作,因爲月份數字是理想的。雖然我不太確定在哪裏添加你上面提到的部分?如果我改變它在查詢的頂部,它會拋出語法錯誤?我添加了一張圖片,如果有幫助。謝謝! – Rob

+0

您可以將它作爲「句點」添加到from語句中,就像'SELECT T0.ItemCode,SUM(T0.Quantity)AS Quantity,T0。WhsCode AS'Warehouse',(12 + datepart(month,getdate()) - datepart(month,t1.docdate))%12 + 1 PERIOD ...',然後將主鍵更改爲[[1],[2 ],[3] ...'我沒有測試過,但它應該可以工作(你也不需要將PERIOD轉換爲varchar) – ZLK

回答

0

你應該使用下面的方法來獲得支點個月,

SELECT Month(GetDate()) 
     ,Month(DateAdd(MONTH,-1,GetDate())) 
     ,Month(DateAdd(MONTH,-2,GetDate())) 
     ,Month(DateAdd(MONTH,-3,GetDate())) 
     ,Month(DateAdd(MONTH,-4,GetDate())) 
     ,Month(DateAdd(MONTH,-5,GetDate())) 
     ,Month(DateAdd(MONTH,-6,GetDate())) 
     ,Month(DateAdd(MONTH,-7,GetDate())) 
     ,Month(DateAdd(MONTH,-8,GetDate())) 
     ,Month(DateAdd(MONTH,-9,GetDate())) 
     ,Month(DateAdd(MONTH,-10,GetDate())) 
     ,Month(DateAdd(MONTH,-11,GetDate())) 
1

所以你們兩個在這裏選擇...

首先是要改變你的支點是這樣的:

SELECT * 
FROM 
(
    SELECT T0.ItemCode,SUM(T0.Quantity) AS Quantity, T0.WhsCode AS 'Warehouse', (12 + DATEPART(MONTH, GETDATE()) - DATEPART(MONTH, t1.docDate)) % 12 + 1 PERIOD 
    FROM INV1 T0 
    INNER JOIN OINV T1 on T0.DocEntry = T1.DocEntry 
    WHERE T1.Canceled = 'N' 
    AND T0.ItemCode = '75910' AND DATEDIFF(m, T0.DocDate,getdate()) < 12 
    GROUP BY T0.ItemCode, T0.WhsCode,datepart(YEAR,T1.DocDate),datepart(MONTH,T1.DocDate) 
    ) S 
PIVOT (SUM(QUANTITY) FOR [PERIOD] IN 
([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) P 

這將生成項目代碼,倉庫,1,2,3,4,5,6,7,8,9,10,11,12作爲列,其中1將始終是當前月份,2將會alw ays是前一個月,3將是前一個月,等等......

這很不方便,因爲您必須真正計算出月份值是什麼,但是這將始終按照此順序執行。

你的另一種選擇是...更乏味一點...你需要使用一大堆IF語句來產生你想要的結果。例如,

IF DATEPART(MONTH, GETDATE()) = 1 
BEGIN 
    SELECT * 
    FROM 
    (
     SELECT T0.ItemCode,SUM(T0.Quantity) AS Quantity, T0.WhsCode AS 'Warehouse',datepart(MONTH,t1.docdate) PERIOD 
     FROM INV1 T0 
     INNER JOIN OINV T1 on T0.DocEntry = T1.DocEntry 
     WHERE T1.Canceled = 'N' 
     AND T0.ItemCode = '75910' AND DATEDIFF(m, T0.DocDate,getdate()) < 12 
     GROUP BY T0.ItemCode, T0.WhsCode, datepart(YEAR,T1.DocDate), datepart(MONTH,T1.DocDate) 
     ) S 
    PIVOT (SUM(QUANTITY) FOR [PERIOD] IN 
    ([1],[12],[11],[10],[9],[8],[7],[6],[5],[4],[3],[2])) P 
END 
ELSE IF DATEPART(MONTH, GETDATE()) = 2 
BEGIN 
    SELECT * 
    FROM 
    (
     SELECT T0.ItemCode,SUM(T0.Quantity) AS Quantity, T0.WhsCode AS 'Warehouse',datepart(MONTH,t1.docdate) PERIOD 
     FROM INV1 T0 
     INNER JOIN OINV T1 on T0.DocEntry = T1.DocEntry 
     WHERE T1.Canceled = 'N' 
     AND T0.ItemCode = '75910' AND DATEDIFF(m, T0.DocDate,getdate()) < 12 
     GROUP BY T0.ItemCode, T0.WhsCode, datepart(YEAR,T1.DocDate), datepart(MONTH,T1.DocDate) 
     ) S 
    PIVOT (SUM(QUANTITY) FOR [PERIOD] IN 
    ([2],[1],[12],[11],[10],[9],[8],[7],[6],[5],[4],[3])) P -- note this part changes depending on the datepart(month, getdate()) value 
END 
ELSE IF DATEPART(MONTH, GETDATE()) = 3 
BEGIN 
    ... 

基本上,在這裏寫出12個不同的if語句。但有優勢,這是否有是,而不是換了個號碼,你可以,如果你改變查詢略有...例如使用的月份名稱,

IF DATEPART(MONTH, GETDATE()) = 1 
BEGIN 
    SELECT * 
    FROM 
    (
     SELECT T0.ItemCode,SUM(T0.Quantity) AS Quantity, T0.WhsCode AS 'Warehouse', months.name PERIOD 
     FROM INV1 T0 
     INNER JOIN OINV T1 on T0.DocEntry = T1.DocEntry 
     INNER JOIN (VALUES (1, 'Jan'), (2, 'Feb'), (3, 'Mar'), (4, 'Apr'), (5, 'May'), (6, 'Jun'), (7, 'Jul'), (8, 'Aug'), (9, 'Sep'), (10, 'Oct'), (11, 'Nov'), (12, 'Dec')) months(num, name) ON datepart(MONTH, T1.DocDate) = months.num 
     WHERE T1.Canceled = 'N' 
     AND T0.ItemCode = '75910' AND DATEDIFF(m, T0.DocDate,getdate()) < 12 
     GROUP BY T0.ItemCode, T0.WhsCode, datepart(YEAR,T1.DocDate), datepart(MONTH,T1.DocDate) 
     ) S 
    PIVOT (SUM(QUANTITY) FOR [PERIOD] IN 
    ([Jan],[Dec],[Nov],[Oct],[Sep],[Aug],[Jul],[Jun],[May],[Apr],[Mar],[Feb])) P 
END 
ELSE IF DATEPART(MONTH, GETDATE()) = 2 
BEGIN 
    SELECT * 
    FROM 
    (
     SELECT T0.ItemCode,SUM(T0.Quantity) AS Quantity, T0.WhsCode AS 'Warehouse', months.name PERIOD 
     FROM INV1 T0 
     INNER JOIN OINV T1 on T0.DocEntry = T1.DocEntry 
     INNER JOIN (VALUES (1, 'Jan'), (2, 'Feb'), (3, 'Mar'), (4, 'Apr'), (5, 'May'), (6, 'Jun'), (7, 'Jul'), (8, 'Aug'), (9, 'Sep'), (10, 'Oct'), (11, 'Nov'), (12, 'Dec')) months(num, name) ON datepart(MONTH, T1.DocDate) = months.num 
     WHERE T1.Canceled = 'N' 
     AND T0.ItemCode = '75910' AND DATEDIFF(m, T0.DocDate,getdate()) < 12 
     GROUP BY T0.ItemCode, T0.WhsCode, datepart(YEAR,T1.DocDate), datepart(MONTH,T1.DocDate) 
     ) S 
    PIVOT (SUM(QUANTITY) FOR [PERIOD] IN 
    ([Feb],[Jan],[Dec],[Nov],[Oct],[Sep],[Aug],[Jul],[Jun],[May],[Apr],[Mar])) P -- note this part changes depending on the datepart(month, getdate()) value 
END 
ELSE IF DATEPART(MONTH, GETDATE()) = 3 
BEGIN 
    ...