Utworzyłem tsrange_interception_agg
agregat
create function tsrange_interception (
internal_state tsrange, next_data_values tsrange
) returns tsrange as $$
select internal_state * next_data_values;
$$ language sql;
create aggregate tsrange_interception_agg (tsrange) (
sfunc = tsrange_interception,
stype = tsrange,
initcond = $$[-infinity, infinity]$$
);
Następnie to zapytanie
with td (id, begin_time, end_time) as
(
values
(1, '2014-01-01'::timestamp, '2014-01-31'::timestamp),
(1, '2014-02-01', '2014-02-28'),
(1, '2014-04-01', '2014-04-30'),
(2, '2014-01-15', '2014-02-20'),
(2, '2014-04-15', '2014-05-05'),
(3, '2014-01-20', '2014-04-20')
), ranges as (
select
id,
row_number() over(partition by id) as rn,
tsrange(begin_time, end_time) as tr
from td
), cr as (
select r0.tr tr0, r1.tr as tr1
from ranges r0 cross join ranges r1
where
r0.id < r1.id and
r0.tr && r1.tr and
r0.id = (select min(id) from td)
)
select tr0 * tsrange_interception_agg(tr1) as interseptions
from cr
group by tr0
having count(*) = (select count(distinct id) from td) - 1
;
interseptions
-----------------------------------------------
["2014-02-01 00:00:00","2014-02-20 00:00:00")
["2014-01-20 00:00:00","2014-01-31 00:00:00")
["2014-04-15 00:00:00","2014-04-20 00:00:00")