在MySQL中计算重叠日期时间范围的总数

3

我有一个问题,几乎与Sum amount of overlapping datetime ranges in MySQL相同,所以我正在重复使用他的部分文本,希望这样做没问题...

我有一个MySQL表格,其中包含每个事件的StartTime和EndTime(作为DateTime类型)。

我尝试输出每种事件重叠时间的总和以及重叠事件的数量。

在MySQL中执行此查询的最有效/简单的方法是什么?

CREATE TABLE IF NOT EXISTS `events` (
  `EventID` int(10) unsigned NOT NULL auto_increment,
  `EventType` int(10) unsigned NOT NULL,
  `StartTime` datetime NOT NULL,
  `EndTime` datetime default NULL,
  PRIMARY KEY  (`EventID`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=37 ;


INSERT INTO `events` (`EventID`, EventType,`StartTime`, `EndTime`) VALUES
(10001,1, '2009-02-09 03:00:00', '2009-02-09 10:00:00'),
(10002,1, '2009-02-09 05:00:00', '2009-02-09 09:00:00'),
(10003,1, '2009-02-09 07:00:00', '2009-02-09 09:00:00'),
(10004,3, '2009-02-09 11:00:00', '2009-02-09 13:00:00'),
(10005,3, '2009-02-09 12:00:00', '2009-02-09 14:00:00');


# if the query was run using the data above,
# the table below would be the desired output

# Number of Overlapped Events , The event type, | Total Amount of Time those events overlapped.
1,1, 03:00:00
2,1, 02:00:00
3,1, 02:00:00
1,3, 01:00:00

这里有一个非常优秀的解决方案,由Mark Byers提供,我想知道是否可以将其扩展以包括“事件类型”。

他的解决方案没有事件类型:

SELECT `COUNT`, SEC_TO_TIME(SUM(Duration))
FROM (
    SELECT
        COUNT(*) AS `Count`,
        UNIX_TIMESTAMP(Times2.Time) - UNIX_TIMESTAMP(Times1.Time) AS Duration
    FROM (
        SELECT @rownum1 := @rownum1 + 1 AS rownum, `Time`
        FROM (
            SELECT DISTINCT(StartTime) AS `Time` FROM events
            UNION
            SELECT DISTINCT(EndTime) AS `Time` FROM events
        ) AS AllTimes, (SELECT @rownum1 := 0) AS Rownum
        ORDER BY `Time` DESC
    ) As Times1
    JOIN (
        SELECT @rownum2 := @rownum2 + 1 AS rownum, `Time`
        FROM (
            SELECT DISTINCT(StartTime) AS `Time` FROM events
            UNION
            SELECT DISTINCT(EndTime) AS `Time` FROM events
        ) AS AllTimes, (SELECT @rownum2 := 0) AS Rownum
        ORDER BY `Time` DESC
    ) As Times2
    ON Times1.rownum = Times2.rownum + 1
    JOIN events ON Times1.Time >= events.StartTime AND Times2.Time <= events.EndTime
    GROUP BY Times1.rownum
) Totals
GROUP BY `Count`

如果两个事件重叠但它们具有不同的事件类型,应该发生什么? - Mark Byers
它们不会被视为重叠,因为它们是不同类型的。你对原问题的解决方案真的很漂亮,如果你能扩展它以包括事件类型,那对我来说就完美了。 - Balroq
1个回答

1
SELECT
  COUNT(*) as occurrence
  , sub.event_id
  , SEC_TO_TIME(SUM(LEAST(e1end, e2end) - GREATEST(e1start, e2start)))) as duration
FROM
  (  SELECT  
      , e1.event_id
      , UNIX_TIMESTAMP(e1.starttime) as e1start
      , UNIX_TIMESTAMP(e1.endtime) as e1end
      , UNIX_TIMESTAMP(e2.starttime) as e2start
      , UNIX_TIMESTAMP(e2.endtime) as e2end
    FROM events e1
    INNER JOIN events e2 
      ON (e1.eventtype = e2.eventtype AND e1.id <> e2.id
      AND NOT(e1.starttime > e2.endtime OR e1.endtime < e2.starttime))
  ) sub
GROUP BY sub.event_id 
ORDER BY occurrence DESC

太棒了,谢谢!但它不能正确计算所有情况下的 duration。您需要更改为 SEC_TO_TIME(SUM(LEAST(e1end, e2end) - GREATEST(e1start, e2start)))) as duration - happy_marmoset

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接