假设我有一个如下表
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查询运行时间更长,并且进入不响应模式。
我无法解决此问题。有人可以帮忙吗?
谢谢!
答案 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;