SQL select 重叠行

SQL select overlap rows

我得到这个 table 操作:

+-----------+---------------------+----------+
| theatreNo |    startDateTime    | duration |
+-----------+---------------------+----------+
|         1 | 2019-05-12 09:30:00 | 04:50:00 |
|         3 | 2019-05-17 15:05:00 | 02:00:00 |
|         3 | 2019-05-17 16:05:00 | 03:00:00 |
+-----------+---------------------+----------+

我想知道我们是否有两个操作重叠的剧院,它应该输出这个:

+--------+---------------+----------+----------+
| roomNo | startDateTime | firstOp  | secondOp |
+--------+---------------+----------+----------+
|      3 | 2019-05-17    | 15:05:00 | 16:05:00 |
+--------+---------------+----------+----------+

它是重叠的,因为一个操作从 15:05 开始,持续时间为 2 小时,而同一剧院中的另一个操作从 16:05 开始,但第一个操作尚未完成。

我不知道是否有某种方法可以计算开始时间和持续时间之间的差异,并将其与下一个操作的开始时间进行比较。

您可以使用 join 在同一行中获取重叠对:

select o.*, o2.*
from operation o join
     operation o2
     on o2.theatreNo = o.theatreNo and
        o2.startDateTime < o.startDateTime + o.duration and
        o2.startDateTime + o2.duration > o.startDateTime and
        (o2.startDateTime <> o.startDateTime or
         o2.duration <> o.duration
        );

如果您想总结重叠部分,逻辑会变得更加困难。问题是多个时间段可能会重叠。您可以在同一行中获得任何一对 - 但该对可能与另一对重叠,因此会有冗余。

您可以使用ADDTIME()查找manual here。 在手册中,您还会找到 DATE()TIME()

SELECT o1.theatreNo as roomNo,
       DATE(o1.startDateTime) as startDateTime, 
       TIME(o1.startDateTime) as firstOp, 
       TIME(o2.startDateTime) as secondOp
FROM operation o1
JOIN operation o2 ON o1.theatreNo = o2.theatreNo
WHERE o1.startDateTime < ADDTIME(o2.startDateTime,o2.duration)
AND ADDTIME(o1.startDateTime,o1.duration) > o2.startDateTime
AND o1.startDateTime < o2.startDateTime;

DEMO

可以有N个重叠。

因此,如果您期望我们可以在考虑 N 种可能性的概率的情况下创建一些查询,其中 0<=N<=M(N = 重叠数,M = 案例数),那么对于下面给出的输入案例,结果将多次显示相同的 "roomNo" 或 "theatreNo"。

+-----------+---------------------+----------+
| theatreNo |    startDateTime    | duration |
+-----------+---------------------+----------+
|         1 | 2019-05-12 09:30:00 | 04:50:00 |
|         3 | 2019-05-17 15:05:00 | 02:00:00 |
|         3 | 2019-05-17 16:05:00 | 03:00:00 |
|         3 | 2019-05-17 17:05:00 | 03:00:00 |
+-----------+---------------------+----------+

它会给出如下答案

+--------+---------------+----------+----------+
| roomNo | startDateTime | firstOp  | secondOp |
+--------+---------------+----------+----------+
|      3 | 2019-05-17    | 15:05:00 | 16:05:00 |
|      3 | 2019-05-17    | 16:05:00 | 17:05:00 |
+--------+---------------+----------+----------+

为避免这种情况,您可以使用以下显示所有重叠的查询

SELECT o1.theatreNo as roomNo,
       DATE(o1.startDateTime) as startDateTime, 
       TIME(o1.startDateTime) as firstOp, 
       GROUP_CONCAT(TIME(o2.startDateTime)) as allOp
FROM operation o1
JOIN operation o2 ON o1.theatreNo = o2.theatreNo
WHERE o1.startDateTime < ADDTIME(o2.startDateTime,o2.duration)
AND ADDTIME(o1.startDateTime,o1.duration) > o2.startDateTime
AND o1.startDateTime < o2.startDateTime;

这会给你以下结果

+--------+---------------+----------+--------------------+
| roomNo | startDateTime | firstOp  | allOp              |
+--------+---------------+----------+--------------------+
|      3 | 2019-05-17    | 15:05:00 | 16:05:00, 17:05:00 |
+--------+---------------+----------+--------------------+

DEMO