我有一个包含事件的数据库表:
CREATE TABLE events
event VARCHAR(32)
,down_time TIMESTAMP
,up_time TIMESTAMP
,id INT UNSIGNED NOT NULL AUTO_INCREMENT KEY
,INDEX(event(16))
);
INSERT INTO events(event, down_time, up_time) VALUES
('e1', '2015-01-01 00:00:04', '2015-01-01 00:00:08'),
('e2', '2015-01-01 00:00:05', '2015-01-01 00:00:06'),
('e3', '2015-01-01 00:00:02', '2015-01-01 00:00:09'),
('e4', '2015-01-01 00:00:01', '2015-01-01 00:00:07'),
('e5', '2015-01-01 00:00:03', '2015-01-01 00:00:10');
SELECT * FROM events;
+-------+---------------------+---------------------+----+
| event | down_time | up_time | id |
+-------+---------------------+---------------------+----+
| e1 | 2015-01-01 00:00:04 | 2015-01-01 00:00:08 | 1 |
| e2 | 2015-01-01 00:00:05 | 2015-01-01 00:00:06 | 2 |
| e3 | 2015-01-01 00:00:02 | 2015-01-01 00:00:09 | 3 |
| e4 | 2015-01-01 00:00:01 | 2015-01-01 00:00:07 | 4 |
| e5 | 2015-01-01 00:00:03 | 2015-01-01 00:00:10 | 5 |
+-------+---------------------+---------------------+----+
5 rows in set (0.00 sec)
1 2 3 4 5 6 7 8 9 10
| | | | | | | | | |
| | | |-------e1------| | |
| | | | |-e2| | | | |
| |--------------e3-----------| |
|----------e4-----------| | | |
| | |-------------e5------------|
我想确定所有事件是否在任何时候重叠。 所以在上面它们都在这里相交(e2):
Overlap |overlap_down_time | overlap_up_time | overlap_duration
1 |2015-01-01 00:00:05 | 2015-01-01 00:00:06 | 00:00:01
我可以使用此查询找到事件对之间的重叠但不确定如何包含所有事件..非常感谢提前!
SELECT
e1.event AS event1_name,
e1.down_time AS event1_down_time,
e1.up_time AS event1_up_time,
TIMEDIFF(e1.up_time, e1.down_time) AS event1_duration,
e2.event AS event2_name,
e2.down_time AS event2_down_time,
e2.up_time AS event2_up_time,
TIMEDIFF(e2.up_time, e2.down_time) AS event1_duration,
GREATEST(e1.down_time,e2.down_time) AS overlap_down_time,
LEAST(e1.up_time,e2.up_time) AS overlap_up_time,
TIMEDIFF( LEAST(e1.up_time,e2.up_time),
GREATEST(e1.down_time,e2.down_time) ) AS overlap_duration
FROM events e1
INNER JOIN events e2 ON e1.id < e2.id
WHERE
( e2.down_time <= e1.up_time )
AND
( e2.up_time >= e1.down_time );
下面提出的解决方案似乎不包括事件在整个时间范围内发生两次的情况..对于以下e2发生:
1 2 3 4 5 6 7 8 9 10
| | | |-------e1------| | |
| | |---e2--| |-------e2------|
| |-------------e3------------| |
|----------e4-----------| | | |
INSERT INTO events(event, down_time, up_time) VALUES
('e1', '2015-01-01 00:00:04', '2015-01-01 00:00:08'),
('e2', '2015-01-01 00:00:03', '2015-01-01 00:00:05'),
('e2', '2015-01-01 00:00:06', '2015-01-01 00:00:10'),
('e3', '2015-01-01 00:00:02', '2015-01-01 00:00:09'),
('e4', '2015-01-01 00:00:01', '2015-01-01 00:00:07');
我已经能够通过使用两阶段查询来识别交叉点:
CREATE VIEW overlap1 AS
SELECT
CONCAT(a.event,'-', b.event) overlaps,
GREATEST(a.down_time,b.down_time) AS downtime,
LEAST(a.up_time,b.up_time) AS uptime,
TIME_TO_SEC(TIMEDIFF( LEAST(a.up_time,b.up_time),
GREATEST(a.down_time,b.down_time))) AS duration
FROM events a
JOIN events b
ON a.event < b.event
AND (a.event = 'e1' OR a.event = 'e2' OR a.event = 'e3' OR a.event = 'e4')
AND (b.event = 'e1' OR b.event = 'e2' OR b.event = 'e3' OR b.event = 'e4')
WHERE ( a.down_time <= b.up_time )
AND ( a.up_time >= b.down_time );
SELECT * FROM overlap1;
+----------+---------------------+---------------------+----------+
| overlaps | downtime | uptime | duration |
+----------+---------------------+---------------------+----------+
| e1-e2 | 2015-01-01 00:00:04 | 2015-01-01 00:00:05 | 1 |
| e1-e2 | 2015-01-01 00:00:06 | 2015-01-01 00:00:08 | 2 |
| e1-e3 | 2015-01-01 00:00:04 | 2015-01-01 00:00:08 | 4 |
| e2-e3 | 2015-01-01 00:00:03 | 2015-01-01 00:00:05 | 2 |
| e2-e3 | 2015-01-01 00:00:06 | 2015-01-01 00:00:09 | 3 |
| e1-e4 | 2015-01-01 00:00:04 | 2015-01-01 00:00:07 | 3 |
| e2-e4 | 2015-01-01 00:00:03 | 2015-01-01 00:00:05 | 2 |
| e2-e4 | 2015-01-01 00:00:06 | 2015-01-01 00:00:07 | 1 |
| e3-e4 | 2015-01-01 00:00:02 | 2015-01-01 00:00:07 | 5 |
+----------+---------------------+---------------------+----------+
CREATE VIEW overlap2 AS
SELECT
CONCAT(a.overlaps,'-',b.overlaps) AS overlaps,
GREATEST(a.downtime,b.downtime) AS downtime,
LEAST(a.uptime,b.uptime) AS uptime,
TIMEDIFF( LEAST(a.uptime,b.uptime),
GREATEST(a.downtime,b.downtime) ) AS duration
FROM overlap1 a
JOIN overlap1 b
ON a.overlaps < b.overlaps
AND (a.overlaps = 'e1-e2' OR a.overlaps = 'e3-e4')
AND (b.overlaps = 'e1-e2' OR b.overlaps = 'e3-e4')
WHERE ( a.downtime <= b.uptime )
AND ( a.uptime >= b.downtime );
SELECT * FROM overlap2;
+-------------+---------------------+---------------------+----------+
| overlaps | downtime | uptime | duration |
+-------------+---------------------+---------------------+----------+
| e1-e2-e3-e4 | 2015-01-01 00:00:04 | 2015-01-01 00:00:05 | 00:00:01 |
| e1-e2-e3-e4 | 2015-01-01 00:00:06 | 2015-01-01 00:00:07 | 00:00:01 |
+-------------+---------------------+---------------------+----------+
如果可能的话,我想用一个查询来实现这一点..非常感谢!
答案 0 :(得分:0)
以下查询将符合您的要求:
select e1.* from events e1
join events e2 on e1.down_time>=e2.down_time and e1.up_time<=e2.up_time
group by e1.event
having count(*)=(select count(*) from events)
验证结果
答案 1 :(得分:0)
以下查询获取最小持续时间项并检查其他记录是否属于范围:
resultList.stream().filter(p->p.getName().equals(listRange.any).collect();
SELECT
1 Overlap,
ev.down_time overlap_down_time,
ev.up_time,
SEC_TO_TIME(ev.secondsdiff) overlap_duration
FROM
(SELECT
COUNT(ev1.id) matchcount, ev2.*
FROM
events ev1
JOIN (SELECT
*
FROM
(SELECT
TIMESTAMPDIFF(SECOND, down_time, up_time) secondsdiff, ev.*
FROM
events ev) minevent
ORDER BY secondsdiff ASC
LIMIT 1) ev2 ON (ev1.down_time <= ev2.down_time
AND ev1.up_time >= ev2.up_time)) ev
WHERE
ev.matchcount = (SELECT
COUNT(id)
FROM
events);