计算 MySQL 中重叠日期范围的最大数量
Count maximum number of overlapping date ranges in MySQL
下面的情况让我很头疼。在 MySQL 我有一个 table 有超过 40000 个条目,看起来像这样:
create table if not exists sessions
(
startt datetime null,
endt datetime null,
id int auto_increment
primary key
);
INSERT INTO sessions (startt, endt, id) VALUES
('2020-02-06 10:33:55', '2020-02-06 10:34:41', 20356),
('2020-02-06 10:33:14', '2020-02-06 10:33:57', 20355),
('2020-02-06 10:32:55', '2020-02-06 10:33:32', 20354),
('2020-02-06 10:33:03', '2020-02-06 10:33:12', 20353),
('2020-02-06 10:31:38', '2020-02-06 10:32:41', 20352),
('2020-02-06 09:48:44', '2020-02-06 09:50:37', 20351);
SELECT * FROM sessions;
+---------------------+---------------------+-------+
| startt | endt | id |
+---------------------+---------------------+-------+
| 2020-02-06 10:33:55 | 2020-02-06 10:34:41 | 20356 |
| 2020-02-06 10:33:14 | 2020-02-06 10:33:57 | 20355 |
| 2020-02-06 10:32:55 | 2020-02-06 10:33:32 | 20354 |
| 2020-02-06 10:33:03 | 2020-02-06 10:33:12 | 20353 |
| 2020-02-06 10:31:38 | 2020-02-06 10:32:41 | 20352 |
| 2020-02-06 09:48:44 | 2020-02-06 09:50:37 | 20351 |
+---------------------+---------------------+-------+
6 rows in set (0.00 sec)
fiddle https://www.db-fiddle.com/f/49bNZ7863gv6RThoPpuiid/0
日期和时间范围是会话。我想知道的是:一次存在的最大会话数是多少?
我发现了很多东西,比如如何找出一个日期是否在其他日期的范围内等。这些都没有真正帮助,因为我想找出最大峰值时有多少用户。
这是一个使用 window 函数的选项(在 MySQL 8.0 中可用):
select dt, sum(nb) over(order by dt) sum_nb
from (
select starttt dt, 1 nb from mytable
union all select endt, -1 from mytable
) t
order by sum_nb desc
limit 1
想法是对数据集进行逆透视;并发会话数在每个会话开始时增加 1,在结束时减少 1。
然后您可以用 window 总和计算每个时间点的并发会话数。
最后一步是按会话计数排序并仅保留第一行。
我将其表述为具有 window 函数的聚合:
select dt, sum(sum(inc)) over (order by dt) as overlapping
from (select starttt as dt, 1 as inc
from mytable union all
select endt, -1 as inc
from mytable
) t
group by dt
order by overlapping desc
limit 1;
下面的情况让我很头疼。在 MySQL 我有一个 table 有超过 40000 个条目,看起来像这样:
create table if not exists sessions
(
startt datetime null,
endt datetime null,
id int auto_increment
primary key
);
INSERT INTO sessions (startt, endt, id) VALUES
('2020-02-06 10:33:55', '2020-02-06 10:34:41', 20356),
('2020-02-06 10:33:14', '2020-02-06 10:33:57', 20355),
('2020-02-06 10:32:55', '2020-02-06 10:33:32', 20354),
('2020-02-06 10:33:03', '2020-02-06 10:33:12', 20353),
('2020-02-06 10:31:38', '2020-02-06 10:32:41', 20352),
('2020-02-06 09:48:44', '2020-02-06 09:50:37', 20351);
SELECT * FROM sessions;
+---------------------+---------------------+-------+
| startt | endt | id |
+---------------------+---------------------+-------+
| 2020-02-06 10:33:55 | 2020-02-06 10:34:41 | 20356 |
| 2020-02-06 10:33:14 | 2020-02-06 10:33:57 | 20355 |
| 2020-02-06 10:32:55 | 2020-02-06 10:33:32 | 20354 |
| 2020-02-06 10:33:03 | 2020-02-06 10:33:12 | 20353 |
| 2020-02-06 10:31:38 | 2020-02-06 10:32:41 | 20352 |
| 2020-02-06 09:48:44 | 2020-02-06 09:50:37 | 20351 |
+---------------------+---------------------+-------+
6 rows in set (0.00 sec)
fiddle https://www.db-fiddle.com/f/49bNZ7863gv6RThoPpuiid/0
日期和时间范围是会话。我想知道的是:一次存在的最大会话数是多少?
我发现了很多东西,比如如何找出一个日期是否在其他日期的范围内等。这些都没有真正帮助,因为我想找出最大峰值时有多少用户。
这是一个使用 window 函数的选项(在 MySQL 8.0 中可用):
select dt, sum(nb) over(order by dt) sum_nb
from (
select starttt dt, 1 nb from mytable
union all select endt, -1 from mytable
) t
order by sum_nb desc
limit 1
想法是对数据集进行逆透视;并发会话数在每个会话开始时增加 1,在结束时减少 1。
然后您可以用 window 总和计算每个时间点的并发会话数。
最后一步是按会话计数排序并仅保留第一行。
我将其表述为具有 window 函数的聚合:
select dt, sum(sum(inc)) over (order by dt) as overlapping
from (select starttt as dt, 1 as inc
from mytable union all
select endt, -1 as inc
from mytable
) t
group by dt
order by overlapping desc
limit 1;