0

I'm trying to think of a way to take two fields entries in a MySQL table (One being a timestamp e.g., '2013-07-31 11:59:46' and the other being a duration of time in seconds e.g., '55' and find all the records that overlap each other and how many of them are overlapped during that period of time. I already have a headache but I'm sure it can be done somehow? What would be a good way to get the return value?

So for instance, say I have a total of 5 entries from Jan 1st

2013-01-01 09:00:00 | 30     (an event that started at 9:00am and lasted 30 seconds)
2013-01-01 09:02:00 | 360    (an event that started at 9:02am and lasted 6 minutes)
2013-01-01 09:03:00 | 600    (an event that started at 9:03am and lasted 10 minutes)
2013-01-01 09:11:00 | 10    (an event that started at 9:11am and lasted 10 seconds)
2013-01-01 09:12:00 | 30    (an event that started at 9:12am and lasted 30 seconds)

Running against these entries I'd get a return value of "2" since that is the maximum amount of concurrent events. (Events #2 & #3 overlap. Then, Event #2 ends before Event #3 and #4 start, which in turn, overlap. This does not change our return value as there are still only two concurrent events at any given time.)

4

1 回答 1

0

考虑以下...

 DROP TABLE IF EXISTS my_table;

 CREATE TABLE my_table
 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
 ,dt DATETIME NOT NULL
 ,duration INT NOT NULL
 );

 INSERT INTO my_table (dt,duration) VALUES
 ('2013-01-01 09:00:00',30),
 ('2013-01-01 09:02:00',360),
 ('2013-01-01 09:03:00',600),
 ('2013-01-01 09:11:00',10),
 ('2013-01-01 09:12:00',30);


  SELECT *
    FROM my_table x
    JOIN my_table y
      ON y.id <> x.id
     AND y.dt < (x.dt + INTERVAL x.duration SECOND)
     AND (y.dt + INTERVAL y.duration SECOND) > x.dt;
 +----+---------------------+----------+----+---------------------+----------+
 | id | dt                  | duration | id | dt                  | duration |
 +----+---------------------+----------+----+---------------------+----------+
 |  3 | 2013-01-01 09:03:00 |      600 |  2 | 2013-01-01 09:02:00 |      360 |
 |  2 | 2013-01-01 09:02:00 |      360 |  3 | 2013-01-01 09:03:00 |      600 |
 |  4 | 2013-01-01 09:11:00 |       10 |  3 | 2013-01-01 09:03:00 |      600 |
 |  5 | 2013-01-01 09:12:00 |       30 |  3 | 2013-01-01 09:03:00 |      600 |
 |  3 | 2013-01-01 09:03:00 |      600 |  4 | 2013-01-01 09:11:00 |       10 |
 |  3 | 2013-01-01 09:03:00 |      600 |  5 | 2013-01-01 09:12:00 |       30 |
 +----+---------------------+----------+----+---------------------+----------+

 or, if you prefer...

  SELECT *
    FROM my_table x
    JOIN my_table y
      ON y.id < x.id
     AND y.dt < (x.dt + INTERVAL x.duration SECOND)
     AND (y.dt + INTERVAL y.duration SECOND) > x.dt;
 +----+---------------------+----------+----+---------------------+----------+
 | id | dt                  | duration | id | dt                  | duration |
 +----+---------------------+----------+----+---------------------+----------+
 |  3 | 2013-01-01 09:03:00 |      600 |  2 | 2013-01-01 09:02:00 |      360 |
 |  4 | 2013-01-01 09:11:00 |       10 |  3 | 2013-01-01 09:03:00 |      600 |
 |  5 | 2013-01-01 09:12:00 |       30 |  3 | 2013-01-01 09:03:00 |      600 |
 +----+---------------------+----------+----+---------------------+----------+

对于“事件 1”,有 2 件事重叠(第 2 项和第 3 项)。对于“事件 2”,有 2 件事重叠(第 3 项和第 4 项)。对于“事件 3”,有 2 件事重叠(第 3 项和第 5 项)。

   9.00  9.01  9.02  9.03  9.04  9.05  9.06  9.07  9.08  9.09  9.10  9.11  9.12  9.13
 1   |-|
 2               |-----------------------------------|
 3                     |-----------------------------------------------------------|
 4                                                                     |-|
 5                                                                           |-|

如果你愿意,我们可以这样说:

nothing overlaps item 1
1 thing overlaps item 2 (item 3), 
3 things overlap item 3 (items 2, 4, & 5), and
1 thing (item 3) overlaps each of items 4 & 5!


 SELECT x.id
      , COUNT(y.id) overlaps
    FROM my_table x
    LEFT
    JOIN my_table y
      ON y.id <> x.id
     AND y.dt < (x.dt + INTERVAL x.duration SECOND)
     AND (y.dt + INTERVAL y.duration SECOND) > x.dt
   GROUP
      By x.id;

 +----+----------+
 | id | overlaps |
 +----+----------+
 |  1 |        0 |
 |  2 |        1 |
 |  3 |        3 |
 |  4 |        1 |
 |  5 |        1 |
 +----+----------+   

一个简单的 ORDER BY 和 LIMIT 将使您获得其中最高的。

我不会在这里接受付款 - 但有些积分会很好!

于 2013-10-22T15:55:15.533 回答