使用GROUP BY创建SELECT语句

时间:2012-05-10 10:51:27

标签: tsql

即使数据库中有数据存在数小时,如何使用所有小时的返回值创建一个包含组的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月。

尝试了一些事情但到目前为止没有任何运气。

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分: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表现不佳。所以明智地使用