按数据分组以获取日期时间范围之间的计数

时间:2019-01-30 10:36:32

标签: sql sql-server datetime

假设我有一个如下表

start_time           end_time             user_name
2019-01-01 00:00:05  2019-01-01 00:05:05  user1
2019-01-01 00:01:35  2019-01-01 00:06:05  user2
2019-01-01 00:02:05  2019-01-01 00:07:05  user3
2019-01-01 00:03:05  2019-01-01 00:08:05  user1
2019-01-01 00:04:05  2019-01-01 00:09:05  user2

我的目标是找出 MINUTE 的登录用户数。像下面这样说

time                  active no of users
2019-01-01 00:00:00   1
2019-01-01 00:01:00   2
2019-01-01 00:02:00   3
2019-01-01 00:03:00   3
2019-01-01 00:04:00   3

现在,我首先尝试为新列dateadd(mi, datediff(mi, 0, dateadd(s, 30, start_time)), 0)安排时间。因此,我将收到上面的表格time

接下来,我试图找到如下所示的四舍五入日期时间的计数

SELECT
dateadd(mi, datediff(mi, 0, dateadd(s, 30, start_time)), 0) as RoundedDateTime,
(
    SELECT  count(distinct(user_name)) 
    FROM entrytable sh
    WHERE (sh.end_time > dateadd(mi, datediff(mi, 0, dateadd(s, 30, t.start_time)), 0) 
    and sh.start_time <= dateadd(mi, datediff(mi, 0, dateadd(s, 30, t.start_time)), 0))        
) as usercounter
FROM entrytable t 

但是,以上的SQL查询运行时间更长,并且进入不响应模式。

我无法解决此问题。有人可以帮忙吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

最简单的解决方案是:

DECLARE @t TABLE (start_time datetime, end_time datetime, user_name varchar(10));
INSERT INTO @t VALUES
('2019-01-01 00:00:05', '2019-01-01 00:05:05', 'user1'),
('2019-01-01 00:01:35', '2019-01-01 00:06:05', 'user2'),
('2019-01-01 00:02:05', '2019-01-01 00:07:05', 'user3'),
('2019-01-01 00:03:05', '2019-01-01 00:08:05', 'user1'),
('2019-01-01 00:04:05', '2019-01-01 00:09:05', 'user2');

SELECT dt AS date_time, SUM(SUM(val)) OVER (ORDER BY dt) AS active_count
FROM (
    SELECT start_time, +1 FROM @t UNION ALL
    SELECT end_time,   -1 FROM @t
) cte1(dt, val)
GROUP BY dt

只要有更改(有人登录或注销),这就会为您提供活动用户的数量。结果:

| date_time               | active_count |
|-------------------------|--------------|
| 2019-01-01 00:00:05.000 | 1            |
| 2019-01-01 00:01:35.000 | 2            |
| 2019-01-01 00:02:05.000 | 3            |
| 2019-01-01 00:03:05.000 | 4            |
| 2019-01-01 00:04:05.000 | 5            |
| 2019-01-01 00:05:05.000 | 4            |
| 2019-01-01 00:06:05.000 | 3            |
| 2019-01-01 00:07:05.000 | 2            |
| 2019-01-01 00:08:05.000 | 1            |
| 2019-01-01 00:09:05.000 | 0            |

请注意,结果中不包含“中间”日期。

答案 1 :(得分:0)

该问题最初是为SQL Server 2012标记的,因此此答案适用于SQL Server。

一种方法是生成分钟列表,然后:

with minutes as (
      select cast('2019-01-01 00:00:00' as datetime) as mm
      union all
      select dateadd(minute, 1, minute)
      from cte
      where mm < '2019-01-01 00:00:05'
     )
select m.*,
       (select count(*)
        from entrytable et
        where et.start_time <= m.mm and
              et.end_time > m.mm
       ) as num_actives
from minutes m;