I don't think there will be a really fast solution to that, as it does require comparing every row in the table with each and every other row in the table (or at least every other row in the specified range).
Assuming your table's primary key column is named id
you could use Postgres' range function to check for overlapping rows:
with check_period (check_range) as (
values ( tstzrange(timestamptz '2018-10-01 00:00:00', timestamptz '2018-10-14 20:15:00') )
)
select id,
start_Time,
end_time,
exists (select *
from the_table t2
cross join check_perioud
where t2.id <> t1.id
and tstzrange(t1.start_time, t1.end_time) && tstzrange(t2.start_time, t2.start_time)
and tstzrange(t2.start_time, t2.start_time) <@ check_range
) has_overlapping_rows
from the_table t1
cross join check_period
where tstzrange(t1.start_time, t1.end_time) <@ check_range;
The CTE check_period
is only there, so that the values for time period you want to analyze are not repeated. If you don't care about repeating them, you can remove it:
select id,
start_Time,
end_time,
exists (select *
from the_table t2
where t2.id <> t1.id
and tstzrange(t1.start_time, t1.end_time) && tstzrange(t2.start_time, t2.start_time)
and tstzrange(t2.start_time, t2.start_time) <@ tstzrange(timestamptz '2018-10-01 00:00:00', timestamptz '2018-10-14 20:15:00')
) has_overlapping_rows
from the_table t1
where tstzrange(t1.start_time, t1.end_time) <@ tstzrange(timestamptz '2018-10-01 00:00:00', timestamptz '2018-10-14 20:15:00');
You should create an index on the timestamp range to make that quick:
create index on the_table( (tstzrange(start_time, end_time), id );
You can extend the above query to return a count of the overlapping rows rather than a true/false flag:
select id,
start_Time,
end_time,
(select count(*)
from the_table t2
where t2.id <> t1.id
and tstzrange(t1.start_time, t1.end_time) && tstzrange(t2.start_time, t2.start_time)
and tstzrange(t2.start_time, t2.start_time) <@ tstzrange(timestamptz '2018-10-01 00:00:00', timestamptz '2018-10-14 20:15:00')
) has_overlapping_rows
from the_table t1
where tstzrange(t1.start_time, t1.end_time) <@ tstzrange(timestamptz '2018-10-01 00:00:00', timestamptz '2018-10-14 20:15:00');
However for rows having many overlapping rows, this will be slower, because the count(*)
forces the database to inspect all overlapping rows. The exists()
solution can stop at the first row found.