sql 服务器中的滚动日历枢轴?

Rolling calendar pivot in sql server?

我已经成功地为自己构建了一个漂亮的小 T-SQL 语句,将计划信息转换为每月的专栏。

SELECT *
FROM 
(
    SELECT 
    t1.customer_code,
    t1.part_number,
    LEFT(DATENAME(month, [formatted_date]),3) as [Month],
    t1.quantity as [quantity] FROM FORECAST_VIEW as t1

    where
        quantity <> 0 
        and formatted_date >= DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)  

) as p
pivot
(
    sum(quantity)
    for [Month] in (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec)
) as p
order by customer_code, part_number

这会产生包含列的输出

customer_code, part_number, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec

并合计每个月所需的 part_number 数量。

这很好用,并且在报告中产生了奇迹,但是如果我可以让月份列从当前月份开始并按顺序排列 12 个月,那将是锦上添花。

问题是我不知道该怎么做。

如果我今天 运行 它的输出将是

customer_code, part_number, Nov, Dec, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct

有人有什么建议吗?

谢谢

编辑 我只是想到,如果我找不到解决方案但它很难看,我不会排除。 我可以将整个 T-SQL 语句放在 IF 块

IF LEFT(DATENAME(month, GETDATE()),3) = 'Nov'
BEGIN
SELECT *
FROM 
(
    ...
) as p
pivot
(   sum(quantity)
    for [Month] in (Nov, Dec, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct)
) as p
order by customer_code, part_number
END

重复 12 次并调整基准月份。

您必须使用动态 SQL 才能实现此目的。

首先,您必须按正确的顺序获取月份名称:

Declare @cols nvarchar(max);

with list as (
    Select n, m = Left(DATENAME(month, DATEADD(month, n, getdate())), 3)
    From (values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11)) as x(n)
)
Select @cols = STUFF((
        Select ', ' + QUOTENAME(m) 
        From list 
        Order By n
        FOR XML PATH(''), TYPE
    ).value('.', 'NVARCHAR(MAX)') 
,1,1,'');

@cols 值将是:[Nov], [Dec], [Jan], [Feb], [Mar], [Apr], [May], [Jun], [Jul], [Aug], [Sep], [Oct]

然后您可以将您的查询与@cols 混合并执行它:

Declare @sql nvarchar(max);

Set @sql = '
    SELECT *
    FROM 
    (
    SELECT 
        t1.customer_code,
        t1.part_number,
        LEFT(DATENAME(month, [formatted_date]),3) as [Month],
        t1.quantity as [quantity] FROM FORECAST_VIEW as t1   
        where
            quantity <> 0 
            and formatted_date >= DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)  
    ) as p
    pivot
    (   sum(quantity)
        for [Month] in ('+@cols+')
    ) as p
    order by customer_code, part_number;

EXEC sp_executesql @sql;

如果您真的不需要动态列名并且可以在代码中使用列名处理它,例如 [0], [1], ... , [11] 表示 12 个月前、11 个月前、...直到上个月,那么您可以使用此查询:

SELECT *
FROM 
(
    SELECT 
    t1.customer_code,
    t1.part_number,
    (12 - DATEPART(month, x) + DATEPART(month, getdate())) % 12 as [Month],
    t1.quantity as [quantity] FROM FORECAST_VIEW as t1

    where
        quantity <> 0 
        and formatted_date >= DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)      
) as p
pivot
(
    sum(quantity)
    for [Month] in ([0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11])
) as p
order by customer_code, part_number

(12 - DATEPART(month, x) + DATEPART(month, getdate())) % 12 将 return 值如:

Date                    | Month
2015-11-23 16:11:57.860 | 0
2015-10-23 16:11:57.860 | 1
2015-09-23 16:11:57.860 | 2
2015-08-23 16:11:57.860 | 3
2015-07-23 16:11:57.860 | 4
2015-06-23 16:11:57.860 | 5
2015-05-23 16:11:57.860 | 6
2015-04-23 16:11:57.860 | 7
2015-03-23 16:11:57.860 | 8
2015-02-23 16:11:57.860 | 9
2015-01-23 16:11:57.860 | 10
2014-12-23 16:11:57.860 | 11