如何在datetime SQL列中按日期和8小时间隔对这些日期进行分组和计数?
我有一个带有列如何在datetime SQL列中按日期和8小时间隔对这些日期进行分组和计数?,sql,sql-server,Sql,Sql Server,我有一个带有列visit\u date的表,它是一个datetime对象,格式为YYYY-MM-DD HH:MI:SS,如下所示: visit_date |visit_id -------------------|----- 2010-11-01 00:02:00|92314 2010-11-01 23:05:21|23498 2010-11-01 12:42:31|12343 2010-11-02 05:13:21|79881 2010-11-02 14:35:15|22134
visit\u date
的表,它是一个datetime
对象,格式为YYYY-MM-DD HH:MI:SS
,如下所示:
visit_date |visit_id
-------------------|-----
2010-11-01 00:02:00|92314
2010-11-01 23:05:21|23498
2010-11-01 12:42:31|12343
2010-11-02 05:13:21|79881
2010-11-02 14:35:15|22134
2010-11-02 16:12:23|12348
2010-11-03 01:22:44|12384
2010-11-03 05:23:41|12394
2010-11-03 15:13:55|99384
我希望在该日期按日期和8小时窗口分组,以便:
interval |count
-------------------|-----
2010-11-01 00:00:00|1
2010-11-01 08:00:00|2
2010-11-01 16:00:00|3
2010-11-02 00:00:00|4
2010-11-02 08:00:00|5
2010-11-02 16:00:00|6
2010-11-03 00:00:00|7
2010-11-03 08:00:00|8
2010-11-03 16:00:00|9
我最初的查询(仅使用日期)是:
但这只是按日期分组
是否有一种推荐的方法来获取每天每个间隔的间隔计数?我见过使用DATEADD
和DATEPART
的实现,但不确定在这种情况下哪种实现最有意义
谢谢 使用
交叉应用
形成4个移位边界值,然后使用案例表达式中的值
生成分组依据
值
SELECT
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end as shift
, count(1) as count
FROM mytable
CROSS APPLY (
select
cast(CAST(visit_date as DATE)as datetime) s1
, dateadd(hh,8,cast(CAST(visit_date as DATE)as datetime)) s2
, dateadd(hh,16,cast(CAST(visit_date as DATE)as datetime)) s3
, dateadd(hh,24,cast(CAST(visit_date as DATE)as datetime)) s4
) ca
GROUP BY
case
when visit_date >= s1 and visit_date < s2 then s1
when visit_date >= s2 and visit_date < s3 then s2
when visit_date >= s3 and visit_date < s4 then s3
end
ORDER BY shift
将小时数添加到您的分组和计数中:
SELECT
CAST(visit_date as DATE),
HOUR(visit_date)/8 as ival8h
count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE), HOUR(visit_date)/8
ORDER BY CAST(visit_date as DATE)
hour函数返回传递日期的小时数,除以8得到间隔的整数,因此0到7变为0,8到16变为1,以此类推
如果您希望将其作为一个固定在8小时一轮的时间重新乘以8,并将其格式化为NN:00:00,或将其添加到日期,因此:
SELECT
DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME) as quantized_date,
count(1) as count
FROM table
GROUP BY DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME)
ORDER BY CAST(visit_date as DATE)
这基本上是将时间向下舍入到较小的8小时市场,并将其添加到午夜。在日期上需要(可能)两次强制转换,因为DATEADD不会在日期上增加小时,只会在datetime上增加小时,但我们需要强制转换到日期,以便将tine元素固定到午夜
如果希望在没有发生事件的时间段中有一个日期和0计数,请使用数字表或行生成器,创建一个日期序列,将真实数据左键连接到其中,然后按假日期对真实数据进行分组计数。我认为SQL Server中的标准方法是使用
dateadd()
和datediff()
:
如何使
计数列?我看不出它有什么逻辑,汉克斯,这很有道理。要重新格式化它,我是否可以简单地将HOUR(visit_date)/8替换为格式(HOUR(visit_date)/00:00')
-格式遵循.net格式系统,因此任何文本都被语音标记包围,第一个00用于将数字填充成两位数,也就是说,您可以选择日期添加(小时(访问日期)/8)*8
小时到演员阵容(访问日期为日期)
(午夜)如果您想将其保留为日期时间,或者进一步使用它,请添加第二个查询来实现上述功能
SELECT
CAST(visit_date as DATE),
HOUR(visit_date)/8 as ival8h
count(1) as count
FROM table
GROUP BY CAST(visit_date as DATE), HOUR(visit_date)/8
ORDER BY CAST(visit_date as DATE)
SELECT
DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME) as quantized_date,
count(1) as count
FROM table
GROUP BY DATEADD(hour, (HOUR(visit_date)/8)*8, CAST(CAST(visit_date as DATE) as DATETIME)
ORDER BY CAST(visit_date as DATE)
select dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3)) as day_hour8,
count(*)
from t
group by dateadd(hour, 0, 3 * (datediff(hour, 0, visit_date) / 3))
order by day_hour8;