1

即使数据库中有几个小时的数据,如何创建一个包含所有小时返回值的分组的 select 语句?

我有以下查询:

SELECT 
    DAY(OccurredAt) AS [Day], 
    DATEPART(HOUR,OccurredAt) AS [Hour], 
    COUNT(ID) AS [Errors]
FROM 
    Database..Error WITH (NOLOCK)
WHERE 
    YEAR(OccurredAt) = 2012 
    AND MONTH(OccurredAt) = 5
GROUP BY 
    DAY(OccurredAt), DATEPART(HOUR,OccurredAt)
ORDER BY 
    DAY(OccurredAt), DATEPART(HOUR,OccurredAt)

它返回如下数据:

Day Hour    Errors
1   1   2
1   4   2
1   6   1
1   7   1
1   9   3
1   10  1
1   11  1
1   14  19
1   15  7
1   16  234
1   17  54
1   18  17
1   19  109
1   20  27
1   22  2
2   6   2
2   7   1
2   8   2
2   9   1
2   10  44
2   11  2
2   15  1
2   16  3
2   18  2
2   19  41
2   20  108
2   21  106
2   22  36
2   23  2

我希望它返回这样的数据:

Day Hour    Errors
1   0   0
1   1   2
1   2   0
1   3   0   
1   4   2
1   5   0
1   6   1
1   7   1
1   8   0
1   9   3
1   10  1
1   11  1
1   12  0
1   13  0
1   14  19
1   15  7
1   16  234
1   17  54
1   18  17
1   19  109
1   20  27
1   21  0
1   22  2
1   23  0

所以基本上我也需要在查询结果中显示零错误的时间。这些将需要在整个日期范围内显示,在本例中为 2012 年 5 月。

尝试了一些东西,但到目前为止没有任何运气。

4

2 回答 2

2

不要使用临时表或 CTE,而是使用永久表。在几乎所有数据库中,拥有一个数字(或整数)表和一个日历表都非常有用。然后像您这样的查询变得容易,因为在这些表上进行外部连接以填充“真实”数据中不存在的缺失数字或日期很简单。当然,这是它们许多其他用途的补充。

另一种方法是通过您的代码分散重复的 CTE 和/或不可维护的硬编码函数。

于 2012-05-10T13:49:09.737 回答
1

这是我用于每天选择东西的查询:

WITH Dates AS (
SELECT
 [Date] = CONVERT(DATETIME,'01/01/2012')
UNION ALL SELECT
 [Date] = DATEADD(DAY, 1, [Date])
FROM
 Dates
WHERE
 Date < '12/31/2012'
) 
SELECT [Date]
FROM Dates
OPTION (MAXRECURSION 400)

您可以按照您喜欢的方式将它扩展为您需要的表的日期连接。

也许不是 100% 的答案,但这应该可以帮助您上路。

编辑:递归 CTE 可能表现不佳。所以明智地使用

于 2012-05-10T10:56:14.527 回答