计算 MySQL 5.6 中重叠日期范围的最大数量
Count maximum number of overlapping date ranges in MySQL 5.6
我正在创建一个汽车租赁应用程序。我试图在给定日期找到重叠的预订。我遇到了一个类似的问题 但这只回答了 MySQL 8.0.
我针对我的问题修改了上面的问题。
我需要 MySQL 5.6 没有 window 功能的解决方案。
create table if not exists BOOKING
(
start datetime null,
end datetime null,
vehicle_id varchar(255),
id int auto_increment
primary key
);
INSERT INTO BOOKING (start, end, vehicle_id)
VALUES
('2020-02-06 10:33:55', '2020-02-07 10:34:41', 111),
('2020-02-08 10:33:14', '2020-02-10 10:33:57', 111),
('2020-02-06 10:32:55', '2020-02-07 10:33:32', 222),
('2020-08-06 10:33:03', '2020-02-11 10:33:12', 111),
('2020-02-12 10:31:38', '2020-02-15 10:32:41', 111),
('2020-02-09 09:48:44', '2020-02-10 09:50:37', 222);
假设如果我给出开始时间为 2020-02-05 结束时间为 2020-02-11,这应该 return 2,因为车辆 111 的最大使用量从 2020-02-06 到 2 2020-02-10
5 6 7 8 9 10 11
<--> <------>
<----------------> (Vehicle Id 111, ANSWER should be 2)
for vehicle id 222, (For same query)
5 6 7 8 9 10 11
<--> <---> (Vehicle Id 222, ANSWER should be 1)
所以我期望输入开始(2020-02-05)和结束(2020-02-11)的总体输出
+---------+-------+
| vehicle | usage |
+---------+-------+
| 111 | 2 |
| 222 | 1 |
+---------+-------+
我需要包含以下内容的解决方案
- 在传递 start_date 和 end_date 时,我的查询将 return 数据仅用于该范围
- 如果没有找到数据应该return
vehicle_id 0
SELECT vehicle_id vehicle, MAX(cnt) `usage`
FROM ( SELECT booking.vehicle_id, timepoints.dt, COUNT(*) cnt
FROM booking
JOIN ( SELECT start dt FROM booking
UNION ALL
SELECT `end` FROM booking ) timepoints ON timepoints.dt BETWEEN booking.start AND booking.`end`
GROUP BY booking.vehicle_id, timepoints.dt ) subquery
GROUP BY vehicle_id;
PS。第 4 行的印刷错误已更正。
租赁开始时出现最大重叠次数(尽管它可能会持续一段时间,这就是您所关心的)。
您可以为每次启动计算此值:
SELECT b.vehicle_id, b.start, COUNT(*)
FROM booking b JOIN
booking b2
ON b2.vehicle_id = b.vehicle_id AND
b2.start <= b.start AND
b2.end > b.start
WHERE b.start <= $end and b.end >= $start
GROUP BY b.vehicle_id, b.start;
那么对于最大值:
SELECT vehicle_id, MAX(overlaps)
FROM (SELECT b.vehicle_id, b.start, COUNT(*) as overlaps
FROM booking b JOIN
booking b2
ON b2.vehicle_id = b.vehicle_id AND
b2.start <= b.start AND b2.end > b.start
GROUP BY b.vehicle_id, b.start
) b
GROUP BY vehicle_id;
Here 是一个 db<>fiddle.
此类查询的性能永远不如使用 window 函数。但是,(vehicle_id, start, end)
上的索引会有所帮助。
我正在创建一个汽车租赁应用程序。我试图在给定日期找到重叠的预订。我遇到了一个类似的问题
我针对我的问题修改了上面的问题。 我需要 MySQL 5.6 没有 window 功能的解决方案。
create table if not exists BOOKING
(
start datetime null,
end datetime null,
vehicle_id varchar(255),
id int auto_increment
primary key
);
INSERT INTO BOOKING (start, end, vehicle_id)
VALUES
('2020-02-06 10:33:55', '2020-02-07 10:34:41', 111),
('2020-02-08 10:33:14', '2020-02-10 10:33:57', 111),
('2020-02-06 10:32:55', '2020-02-07 10:33:32', 222),
('2020-08-06 10:33:03', '2020-02-11 10:33:12', 111),
('2020-02-12 10:31:38', '2020-02-15 10:32:41', 111),
('2020-02-09 09:48:44', '2020-02-10 09:50:37', 222);
假设如果我给出开始时间为 2020-02-05 结束时间为 2020-02-11,这应该 return 2,因为车辆 111 的最大使用量从 2020-02-06 到 2 2020-02-10
5 6 7 8 9 10 11
<--> <------>
<----------------> (Vehicle Id 111, ANSWER should be 2)
for vehicle id 222, (For same query)
5 6 7 8 9 10 11
<--> <---> (Vehicle Id 222, ANSWER should be 1)
所以我期望输入开始(2020-02-05)和结束(2020-02-11)的总体输出
+---------+-------+
| vehicle | usage |
+---------+-------+
| 111 | 2 |
| 222 | 1 |
+---------+-------+
我需要包含以下内容的解决方案
- 在传递 start_date 和 end_date 时,我的查询将 return 数据仅用于该范围
- 如果没有找到数据应该return
vehicle_id 0
SELECT vehicle_id vehicle, MAX(cnt) `usage`
FROM ( SELECT booking.vehicle_id, timepoints.dt, COUNT(*) cnt
FROM booking
JOIN ( SELECT start dt FROM booking
UNION ALL
SELECT `end` FROM booking ) timepoints ON timepoints.dt BETWEEN booking.start AND booking.`end`
GROUP BY booking.vehicle_id, timepoints.dt ) subquery
GROUP BY vehicle_id;
PS。第 4 行的印刷错误已更正。
租赁开始时出现最大重叠次数(尽管它可能会持续一段时间,这就是您所关心的)。
您可以为每次启动计算此值:
SELECT b.vehicle_id, b.start, COUNT(*)
FROM booking b JOIN
booking b2
ON b2.vehicle_id = b.vehicle_id AND
b2.start <= b.start AND
b2.end > b.start
WHERE b.start <= $end and b.end >= $start
GROUP BY b.vehicle_id, b.start;
那么对于最大值:
SELECT vehicle_id, MAX(overlaps)
FROM (SELECT b.vehicle_id, b.start, COUNT(*) as overlaps
FROM booking b JOIN
booking b2
ON b2.vehicle_id = b.vehicle_id AND
b2.start <= b.start AND b2.end > b.start
GROUP BY b.vehicle_id, b.start
) b
GROUP BY vehicle_id;
Here 是一个 db<>fiddle.
此类查询的性能永远不如使用 window 函数。但是,(vehicle_id, start, end)
上的索引会有所帮助。