这似乎应该很容易,但我似乎无法弄明白。我有一个名为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
?
答案 0 :(得分:4)
不要将日期转换为字符串以剥离时间或日期,请使用日期算术。转换为字符串效率较低,还需要扫描整个表格。
如果您要转换为固定长度的字符串,请不要使用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月 - &gt; 3月而不是9月 - &gt;二月,只需更改此行:
+ 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;