【问题标题】:Count maximum number of overlapping date ranges in MySQL 5.6计算 MySQL 5.6 中重叠日期范围的最大数量
【发布时间】:2020-12-10 07:06:21
【问题描述】:

我正在创建一个汽车租赁应用程序。我试图在给定的日期找到重叠的预订。我遇到了一个类似的问题Count maximum number of overlapping date ranges in MySQL,但这仅适用于 MySQL 8.0。

我针对我的问题修改了上述问题。 我需要没有窗口功能的 MySQL 5.6 解决方案。

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 结束,这应该返回 2,因为车辆 111 的最大使用量是 2 从 2020-02-06 到 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)

所以我期望输入 start(2020-02-05) 和 end(2020-02-11) 的整体输出

+---------+-------+
| vehicle | usage |
+---------+-------+
| 111     | 2     |
| 222     | 1     |
+---------+-------+

我需要涵盖以下内容的解决方案

  • 在传递 start_date 和 end_date 时,我的查询将只返回该范围内的数据
  • 如果没有找到数据应该返回vehicle_id 0

【问题讨论】:

  • “我为我的问题修改了上面的问题”,你的意思是说“我从这个链接复制了创建表和插入语句到这里......”但是你真正尝试自己解决什么MySQL 5.6 中的这个问题?
  • 我的意思是我为我的问题推荐了同样的问题。我试过了,但给出了我没有使用的 MySQL8.0 的答案。我不知道如何计算这些重叠的东西
  • 好的,那么你应该阅读How to Ask,而这个:stackoverflow.com/help/on-topic

标签: mysql sql mysql-5.6


【解决方案1】:

租赁开始时会出现最大重叠次数(尽管它可能会持续一段时间,但这就是您所关心的)。

您可以使用以下方法为每次开始计算:

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 是一个 dbfiddle。

此类查询的性能永远不会像使用窗口函数那样好。但是,(vehicle_id, start, end) 上的索引会有所帮助。

【讨论】:

  • 我的输入参数(将由应用程序提供)我要查询的范围/期间的 start_date 和 return_date 放在哪里。正如我在问题中提到的那样。
  • @Jai 。 . .我在第一个查询中添加了where 子句。
【解决方案2】:
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;

fiddle

PS。第 4 行的打印错误已更正。

【讨论】:

  • 我有点困惑,我应该在哪里输入我想要数据的范围的开始日期和结束日期
  • @Jai 取决于任务。如果表范围必须在两个子查询中的范围内,否则在最内的子查询中。无论如何,在小提琴中描述了算法 - 根据其中的步骤更新。
  • @Akina 。 . .虽然这会产生正确的答案,但它比必要的性能密集得多。
猜你喜欢
  • 1970-01-01
  • 2020-02-20
  • 2021-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
相关资源
最近更新 更多