【问题标题】:Include monthly counts including months where data doesn't exist包括每月计数,包括不存在数据的月份
【发布时间】:2013-03-06 01:29:21
【问题描述】:

这似乎应该很容易,但我似乎无法弄清楚。我有一个表,其中包含 Artifact 名称和 Modification_Date 等。我有一个查询,按月获取文档修改次数。有几个月没有修改。由于我在Modification_Date 上进行查询和分组,因此这些月份没有任何修改的返回结果。理想情况下,在结果集中,我希望那里的月份和 Quantity 为 0。

SELECT CONVERT(NVARCHAR(7), Modification_Date, 120) [Month], 
    COUNT(Artifact) as Quantity
    FROM table
WHERE Modification_Date > DATEADD(month, -6, getdate())
GROUP BY CONVERT(NVARCHAR(7), Modification_Date, 120)
ORDER BY [Month] DESC

这让我得到类似的结果:

Month       Quantity
-------     --------
2013-02     10
2012-11     12
2012-10     5
2012-09     29

如您所见,2012 年 12 月和 2013 年 1 月这两个月份不在结果集中。我想在那里用 0 Quantity 表示这些月份,以便我可以在 SQL 报告条形图中使用该数据并将这些月份用 0 值表示。目前在条形图上它完全跳过了这些月份。有没有办法生成过去 6 个月的 yyyy-mm Month 列,而不仅仅是使用 Modification_Date

【问题讨论】:

    标签: sql-server date select reporting-services


    【解决方案1】:

    不要将日期转换为字符串以去除时间或日期,请使用日期算术。转换为字符串效率较低,还需要扫描整个表。

    如果要转换为固定长度的字符串,不要使用NVARCHAR,使用CHAR。您需要在数字日期中支持哪些 Unicode 字符?变音符号?英镑符号?象形文字?

    这是一个示例,它使用目录视图生成 6 行,然后从当前日期减去几个月以按前 6 个月分组(与您当前的方法不同,应使用Modification_Date 上的索引)。第一次看到这并不完全直观,但你可以看到我关于无循环生成集的系列(part 1 | part 2 | part 3)。

    ;WITH x(m) AS 
    (
      SELECT TOP 6 DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) 
        - (ROW_NUMBER() OVER (ORDER BY [object_id])), 0) 
      FROM sys.all_objects
      ORDER BY [object_id]
    )
    SELECT [Month] = x.m, Quantity = COALESCE(COUNT(t.Artifact), 0)
    FROM x
    LEFT OUTER JOIN dbo.tablename AS t
    ON t.Modification_Date >= x.m
    AND t.Modification_Date < DATEADD(MONTH, 1, x.m)
    GROUP BY x.m
    ORDER BY x.m DESC;
    

    请注意,这不包括当前月份。如果您想转换为包括 10 月 -> 3 月而不是 9 月 -> 2 月,只需更改此行:

    + 1 - (ROW_NUMBER() OVER (ORDER BY [object_id])), 0) 
    

    如果格式化为YYYY-MM 是绝对必要的,您可以这样做:

    ;WITH y(m) AS 
    (
      SELECT TOP 6 DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) 
        - (ROW_NUMBER() OVER (ORDER BY [object_id])), 0) 
      FROM sys.all_objects
      ORDER BY [object_id]
    ),
    x([Month], Quantity)
    AS
    (
      SELECT [Month] = y.m, Quantity = COALESCE(COUNT(t.Artifact), 0)
      FROM y
      LEFT OUTER JOIN dbo.tablename AS t
      ON t.Modification_Date >= y.m
      AND t.Modification_Date < DATEADD(MONTH, 1, y.m)
      GROUP BY y.m
    )
    SELECT [Month] = CONVERT(CHAR(7), [Month], 120), Quantity
    FROM x
    ORDER BY [Month] DESC;
    

    【讨论】:

    • 效果很好!太感谢了。你是对的,不需要 NVARCHAR。我见过一个使用它的日期转换示例,并在我的查询中使用它而不考虑它。
    猜你喜欢
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多