问题陈述: 我在消防部门工作,并且正在对我的数据进行统计分析。一个问题是生成一个日历年中每天每小时的服务呼叫数量。我需要一张可以与一年中的每一天和每一天的每一小时发生的火灾联系在一起的桌子。我希望的是以下情况(利用军备时间)
2017年1月1日00:00:00
2017年1月1日01:00:00
2017年1月1日02:00:00
2017年1月1日03:00:00
2017年1月1日04:00:00
2017年1月1日05:00:00
2017年1月1日06:00:00
2017年1月1日07:00:00
2017年1月1日08:00:00
等到年底
2017年12月31日21:00:00
2017年12月31日22:00:00
2017年12月31日23:00:00
年末
该表将使我能够加入火灾事件表,并且我能够统计地计算一天中每一小时和一年中每一天的事故数量。计算表是必需的,因为火灾表中有空隙。例如; 1月1日的0100小时,0200小时和0300小时没有紧急电话打进来。因此,我无法使用火灾事件表进行计算,因为没有关于何时没有电话进来的数据。带有间隙的火灾事件表如下所示:
时间间隔,事件地址
2017年1月1日,榆树街123号00:00:00
2017年1月1日,04:00:00,橡树街456号
2017年1月1日,05:00:00,枫树街789号
(请注意,0100、0200和0300的时间没有发生火灾呼叫。这些是缺口。)因为数据中存在缺口,其中零应该是泊松分布所需的计算平均值,所以这里没有。平均值不正确。
所需的输出: 我的目标是要有一个带有小时表的日历来加入我的火灾事故,以便返回我的结果集。这是查询的草稿,如果有匹配的值,则返回日历表中的每一行以及火灾事件表中的行。
SELECT TimeInterval , COUNT(Incidents) AS [CountOfIncidents] /*this should probably be a COALESCE statement*/ FROM CalendarTable /*all rows from the calendar with hours and rows with data from FireIncidents*/ LEFT OUTER JOIN FireIncidents ON CalendarTable.timeInterval = FireIncidents.TimeInterval GROUP BY TimeInterval
查询将返回我希望实现的目标:
TimeInterval,CountOfIncidents
2017年1月1日00:00:00,5
2017年1月1日01:00:00,0
2017年1月1日02:00:00,0
2017年1月1日03:00:00,0
2017年1月1日04:00:00,2
2017年1月1日05:00:00,1
(请注意0100、0200和0300的小时数为零。这就是我想要的!现在,我可以创建一个直方图,显示有多少小时为零数。或者我可以计算一个平均值,将零次呼叫计为一天的一部分。)
我已经尝试过的内容: 我已经尝试了以下内容,但是我无法弄清楚如何从中创建表格以及如何将其制成成品,如您在下面的“问题”段落中所见。
DECLARE @DayOfYearNumber INT DECLARE @HourNumber INT SET @DayOfYearNumber = 1 SET @HourNumber = 0 PRINT 'Year' + ', ' + 'CalendarDayOfYear' + ', ' + 'HourOfDay' WHILE @DayOfYearNumber < 366 BEGIN SET @HourNumber = 0 WHILE @HourNumber < 24 BEGIN PRINT '2017' + ', ' + CONVERT(VARCHAR, @DayOfYearNumber) + ' ' + CONVERT(VARCHAR, @HourNumber) SET @HourNumber = @HourNumber + 1 END SET @DayOfYearNumber = @DayOfYearNumber + 1 END
问题:
如何在SQL Server 2012中生成日历表,该表将具有一年中的每一天和每一天的每一小时。再次是我的例子
一个简单的方法使用递归:
with d as ( select cast('2017-01-01' as datetime) as dte union all select dateadd(hour, 1, dte) from d where dateadd(hour, 1, dte) < '2018-01-01' ) select d.* from d option (maxrecursion 0);
尽管递归速度出奇地快,但是如果您需要多次递归,则可能需要考虑使用数字表或将其存储在临时表或永久表中。