包括每月计数,包括不存在数据的月份

0 sql-server select date reporting-services

这看起来应该很容易,但我似乎无法弄清楚。我有一张桌子,上面有一个Artifact名字和Modification_Date其他东西。我有一个查询按月获取文档修改计数。有几个月没有任何修改。由于我正在查询和分组,因此Modification_Date没有返回那些没有修改的月份的结果。理想情况下,在结果集中我希望月份为月份,0 为Quantity.

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
Run Code Online (Sandbox Code Playgroud)

这给我带来了类似于以下的结果:

Month       Quantity
-------     --------
2013-02     10
2012-11     12
2012-10     5
2012-09     29
Run Code Online (Sandbox Code Playgroud)

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

Aar*_*and 5

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

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

下面是一个示例,它使用目录视图生成 6 行,然后从当前日期中减去月份,以按前 6 个月进行分组(并且Modification_Date应该使用索引,这与您当前的方法不同)。第一次看到它时,这并不完全直观,但您可以查看我的关于无循环生成集的系列文章(第 1 部分|第 2 部分|第 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;
Run Code Online (Sandbox Code Playgroud)

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

+ 1 - (ROW_NUMBER() OVER (ORDER BY [object_id])), 0) 
Run Code Online (Sandbox Code Playgroud)

如果格式化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;
Run Code Online (Sandbox Code Playgroud)