简体   繁体   中英

Find total duration (in minutes) between multiple rows with overlaps

I have the following table:

start         end
('19:48:43', '21:12:43')
('21:16:36', '21:17:36')
('21:19:22', '21:46:22')
('21:22:41', '22:03:41')
('21:23:29', '22:04:29')

And I need to know the total time (in minutes) between start and end taking into account overlaps. Given the above table, the computation would look like this:

  • row 1's interval doesn't overlap with any other, so we calculate end - start = 84 minutes
  • row 2's interval doesn't overlap with any other, so we calculate end - start = 1 minute
  • row 3, 4, 5's intervals are overlapping, so we calculate the difference between end of row 5 and start of row 3, which is 45 minutes

total = 84 + 1 + 45 = 130 minutes

I'm using SQLite. So far I haven't been able to arrive at any solution.

With a LEFT join of 2 copies of the table to the table itself and aggregation:

WITH cte AS (
  SELECT DISTINCT 
        COALESCE(MIN(ts.start), t.start) start,
        COALESCE(MAX(te.end), t.end) end   
  FROM tablename t
  LEFT JOIN tablename ts ON t.start BETWEEN ts.start AND ts.end
  LEFT JOIN tablename te ON t.end BETWEEN te.start AND te.end
  GROUP BY t.start, t.end
)
SELECT SUM(strftime('%s', end) - strftime('%s', start)) / 60 total 
FROM cte

Or simpler:

WITH cte AS (
  SELECT DISTINCT 
        COALESCE(
          (SELECT MIN(t2.start) 
           FROM tablename t2 
           WHERE t1.start BETWEEN t2.start AND t2.end), t1.start) start,
        COALESCE(
          (SELECT MAX(t2.end) 
           FROM tablename t2 
           WHERE t1.end BETWEEN t2.start AND t2.end), t1.start) end   
  FROM tablename t1
)
SELECT SUM(strftime('%s', end) - strftime('%s', start)) / 60 total 
FROM cte

See the demo .
Results:

total
130

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM