我有一个由一系列时间数据组成的表,如下所示:
+--------+--------------------+---------------------+
| person | start | end |
+--------+--------------------+---------------------+
| a |2014-12-04 13:00:00 | 2014-12-04 14:00:00 |
| a |2014-12-04 13:30:00 | 2014-12-04 14:30:00 |
| b |2014-12-04 13:00:00 | 2014-12-04 14:00:00 |
| b |2014-12-04 13:30:00 | 2014-12-04 14:30:00 |
| b |2014-12-04 14:00:00 | 2014-12-04 15:00:00 |
| a |2014-12-04 19:00:00 | 2014-12-04 20:00:00 |
| a |2014-12-04 19:30:00 | 2014-12-04 20:30:00 |
+--------+--------------------+---------------------+
我想找时间重叠并输出以下内容:
+--------+--------------------+---------------------+
| person | start | end |
+--------+--------------------+---------------------+
| a |2014-12-04 13:00:00 | 2014-12-04 14:30:00 |
| b |2014-12-04 13:00:00 | 2014-12-04 15:00:00 |
| a |2014-12-04 19:00:00 | 2014-12-04 20:30:00 |
+--------+--------------------+---------------------+
所以我正在寻找一个查询来查找时间间隔重叠的实例,我希望看到时间间隔与之相关的人以及最早的时段和最新的时段。
狡猾解释,但我希望你得到这个小说!
答案 0 :(得分:0)
WITH RECURSIVE
的最新版本的sqlite(不能在sqlfiddle.com上工作),这是非常棘手但可能的:
create table intervals (
person text,
start timestamp,
end timestamp
);
insert into intervals values ('a', '2014-12-04 13:00:00', '2014-12-04 14:00:00');
insert into intervals values ('a', '2014-12-04 13:30:00', '2014-12-04 14:30:00');
insert into intervals values ('b', '2014-12-04 13:00:00', '2014-12-04 14:00:00');
insert into intervals values ('b', '2014-12-04 13:30:00', '2014-12-04 14:30:00');
insert into intervals values ('b', '2014-12-04 14:00:00', '2014-12-04 15:00:00');
insert into intervals values ('a', '2014-12-04 19:00:00', '2014-12-04 20:00:00');
insert into intervals values ('a', '2014-12-04 19:30:00', '2014-12-04 20:30:00');
WITH RECURSIVE
merged_intervals(person, start, end) AS (
select person, start, end
from intervals
where not exists (
select * from intervals i2
where i1.person=i2.person
and (i2.start<i1.start and i2.end>=i1.start)
)
UNION ALL
select i1.person, i1.start, i2.end
from merged_intervals i1, intervals i2
where i1.start<=i2.start and i1.end>i2.start and i1.end<i2.end
and i1.person=i2.person
)
select * from merged_intervals i1
where not exists (
select * from merged_intervals i2
where i1.person=i2.person
and (
(i2.start<i1.start and i2.end>i1.start)
or
(i2.end>i1.end and i2.start<i1.end)
)
)
order by start, person
;