Tôi đang tìm một cách hiệu quả để tìm tất cả các giao lộ giữa các tập hợp các dấu thời gian. Nó cần phải làm việc với PostgreSQL 9.2.Tìm tất cả các giao lộ của tất cả các dải ô trong PostgreSQL
Giả sử phạm vi biểu thị thời gian khi một người có mặt để đáp ứng. Mỗi người có thể có một hoặc nhiều khoảng thời gian khi họ có mặt. Tôi muốn tìm tất cả khoảng thời gian khi cuộc họp có thể diễn ra (nghĩa là trong thời gian đó tất cả mọi người đều có mặt).
Đây là những gì tôi đã có cho đến nay. Dường như nó hoạt động, nhưng tôi không nghĩ nó rất hiệu quả, vì nó xem xét tính khả dụng của một người tại một thời điểm.
WITH RECURSIVE td AS
(
-- Test data. Returns:
-- ["2014-01-20 00:00:00","2014-01-31 00:00:00")
-- ["2014-02-01 00:00:00","2014-02-20 00:00:00")
-- ["2014-04-15 00:00:00","2014-04-20 00:00:00")
SELECT 1 AS entity_id, '2014-01-01'::timestamp AS begin_time, '2014-01-31'::timestamp AS end_time
UNION SELECT 1, '2014-02-01', '2014-02-28'
UNION SELECT 1, '2014-04-01', '2014-04-30'
UNION SELECT 2, '2014-01-15', '2014-02-20'
UNION SELECT 2, '2014-04-15', '2014-05-05'
UNION SELECT 3, '2014-01-20', '2014-04-20'
)
, ranges AS
(
-- Convert to tsrange type
SELECT entity_id, tsrange(begin_time, end_time) AS the_range
FROM td
)
, min_max AS
(
SELECT MIN(entity_id), MAX(entity_id)
FROM td
)
, inter AS
(
-- Ranges for the lowest ID
SELECT entity_id AS last_id, the_range
FROM ranges r
WHERE r.entity_id = (SELECT min FROM min_max)
UNION ALL
-- Iteratively intersect with ranges for the next higher ID
SELECT entity_id, r.the_range * i.the_range
FROM ranges r
JOIN inter i ON r.the_range && i.the_range
WHERE r.entity_id > i.last_id
AND NOT EXISTS
(
SELECT *
FROM ranges r2
WHERE r2.entity_id < r.entity_id AND r2.entity_id > i.last_id
)
)
-- Take the final set of intersections
SELECT *
FROM inter
WHERE last_id = (SELECT max FROM min_max)
ORDER BY the_range;
Không liên quan: cung cấp "dữ liệu tĩnh" có thể được thực hiện ngắn hơn mà không cần sử dụng 'select' và 'union' bằng cách sử dụng một giá trị' 'mệnh đề:' giá trị (1, '2014-01-01' :: dấu thời gian, '2014-01-31' :: dấu thời gian), (2, ...) 'và xác định các tên cột trong CTE. –