MySQL 5:如何在工作时间发现客户高峰

MySQL 5:如何在工作时间发现客户高峰,mysql,sql,union,date-arithmetic,interval-intersection,Mysql,Sql,Union,Date Arithmetic,Interval Intersection,我在MySQL中有一个表,上面有客户花费的时间,我需要找出最忙的30分钟 CREATE TABLE Customer (id int NOT NULL AUTO_INCREMENT PRIMARY KEY, customerId int NOT NULL, arrival datetime, leaving datetime); INSERT INTO Customer (customerId, arrival, leaving) VALUES (1,

我在MySQL中有一个表,上面有客户花费的时间,我需要找出最忙的30分钟

CREATE TABLE Customer
   (id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    customerId int NOT NULL,
    arrival datetime,
    leaving datetime);

INSERT INTO Customer
   (customerId, arrival, leaving)
VALUES
   (1, '2018-01-01 10:00:00', '2018-01-01 12:00:00'),
   (2, '2018-01-01 11:00:00', '2018-01-01 12:00:00'),
   (3, '2018-01-01 11:30:00', '2018-01-01 12:30:00'),
   (4, '2018-01-01 13:30:00', '2018-01-01 14:30:00')
;
预期结果类似于时间和客户数量的多个窗口:

   10:00    10:30    1
   10:30    11:00    1
   11:00    11:30    2
   11:30    12:00    3
   12:00    12:30    1

我可以轻松地进行5次sql查询并获得结果(我在类似问题中提出了一些看法),但我不知道如何通过1次查询获得结果


请问如何在MySQL中创建子间隔?Thx

这是一个基于
union all
和窗口函数(SQL 8.0中提供)的解决方案,它让您非常接近:

select 
    dt start_dt,
    lead(dt) over(order by dt) end_dt, 
    sum(sum(cnt)) over(order by dt) cnt
from (
    select arrival dt, 1 cnt from Customer
    union all
    select leaving, -1 from Customer
) t
group by dt
order by dt
逻辑是在每次到达时递增一个全局计数器,在每次离开时递减。然后,您可以聚合并进行窗口求和

与预期结果的唯一区别在于,此查询不会生成固定的时间间隔列表,而是生成客户数量恒定的时间间隔列表,如中所示:

start_dt            | end_dt              | cnt
:------------------ | :------------------ | --:
2018-01-01 10:00:00 | 2018-01-01 11:00:00 |   1
2018-01-01 11:00:00 | 2018-01-01 11:30:00 |   2
2018-01-01 11:30:00 | 2018-01-01 12:00:00 |   3
2018-01-01 12:00:00 | 2018-01-02 12:30:00 |   1
2018-01-02 12:30:00 |                     |   0

下面是一个基于
union all
和窗口函数(SQL 8.0中提供)的解决方案,它让您非常接近:

select 
    dt start_dt,
    lead(dt) over(order by dt) end_dt, 
    sum(sum(cnt)) over(order by dt) cnt
from (
    select arrival dt, 1 cnt from Customer
    union all
    select leaving, -1 from Customer
) t
group by dt
order by dt
逻辑是在每次到达时递增一个全局计数器,在每次离开时递减。然后,您可以聚合并进行窗口求和

与预期结果的唯一区别在于,此查询不会生成固定的时间间隔列表,而是生成客户数量恒定的时间间隔列表,如中所示:

start_dt            | end_dt              | cnt
:------------------ | :------------------ | --:
2018-01-01 10:00:00 | 2018-01-01 11:00:00 |   1
2018-01-01 11:00:00 | 2018-01-01 11:30:00 |   2
2018-01-01 11:30:00 | 2018-01-01 12:00:00 |   3
2018-01-01 12:00:00 | 2018-01-02 12:30:00 |   1
2018-01-02 12:30:00 |                     |   0

多亏了GMB的帖子,我也找到了SQL 5的解决方案 一些人认为:

CREATE OR REPLACE VIEW changeTimeView AS
select arrival AS changeTime, 1 cnt from Customer
union all
select leaving, -1 from Customer
ORDER BY changeTime
创建视图后:

SELECT DISTINCT chT2.changeTime,  (SELECT SUM(chT1.cnt) FROM changeTimeView chT1 WHERE TIMEDIFF(chT1.changeTime,chT2.changeTime)<=0) FROM changeTimeView chT2

多亏了GMB的帖子,我也找到了SQL 5的解决方案 一些人认为:

CREATE OR REPLACE VIEW changeTimeView AS
select arrival AS changeTime, 1 cnt from Customer
union all
select leaving, -1 from Customer
ORDER BY changeTime
创建视图后:

SELECT DISTINCT chT2.changeTime,  (SELECT SUM(chT1.cnt) FROM changeTimeView chT1 WHERE TIMEDIFF(chT1.changeTime,chT2.changeTime)<=0) FROM changeTimeView chT2

您正在运行哪个版本的MySQL?我根据您的提示找到了相应的解决方案。我会写下来的。THX您正在运行哪个版本的MySQL?我根据您的提示找到了相应的解决方案。我会写下来的。这很有效,很好,我将尝试找到MySQL 5的解决方案。谢谢你的作品,太好了,我会努力找到MySQL 5的解决方案。非常感谢。