sql-server - sql server 中的滚动日历枢轴?

标签 sql-server database tsql pivot

我已经成功地为自己构建了一个漂亮的小 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 block 中

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] ], [9 月], [10 月]

然后您可以将您的查询与@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] for 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 将返回如下值:

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

关于sql-server - sql server 中的滚动日历枢轴?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33872030/

相关文章:

sql-server - 需要一种方法来拦截 MSSQL 中的重复键异常

sql-server - 在Sql Server中将int主键转换为bigint

sql从两个表中获取最大数量?

SQL:WHERE 子句中的 IF 子句

sql-server - 不支持关键字 MultipleActiveResultSets

java - 请求 : Microsoft SQL Server JDBC Driver 1. 1

sql - 在一对一关系中插入

mysql - 如何获取mysql中的Rank?

MYSQL自动增量依赖于另一个表

tsql - SQL 查询组合过滤两个字段