动态SQL数据透视表与移动月份

时间:2016-07-13 05:04:51

标签: sql-server

我试图通过SQL Query& amp;创建一个滚动的12个月销售历史记录。数据透视表。我们使用的程序(SAP B1)只有一个简单的SQL编辑器,所以我希望下面的内容可以完成。我环顾四周,发现了各种动态SQL查询,我们的系统似乎并不太喜欢。我基本上想要用类似的东西取代月份     月(GETDATE())

查询

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

Period只返回DocDate的月份。那么Pivot按日历年(7 = 7月,6 = 6月等),所以当前月份首先列出。 我希望底部是下面的部分,但它不起作用。

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

获得&#34; 7&#34;,&#34; 6&#34;回到8。

我希望这是有道理的。类似的东西可能吗?或者它是否必须通过更高级的动态查询来完成?

这是我想要返回的内容,但是当新月开始时,底部的期间会更新。 enter image description here

2 个答案:

答案 0 :(得分: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将始终是前一个月一个月,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
    ...

基本上,在这里写出十二个不同的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
    ...

答案 1 :(得分: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()))