I have a table in PostgreSQL 9.2 that looks like this (simplified):
CREATE TABLE my_features
(
id integer NOT NULL,
feature_id integer NOT NULL,
begin_time timestamp NOT NULL,
end_time timestamp
)
For each feature_id there may be multiple rows with time ranges specified by begin_time/end_time. They may overlap, but this is relatively rare. I'm looking for a fast way to find all feature_ids that have/don't have any overlaps.
I tried to do this using window functions, like this:
SELECT feature_id, bool_or(end_time > lead(begin_time) OVER ts_win) OVER ts_win AS overlaps_any
FROM my_features
WINDOW ts_win AS (PARTITION BY feature_id ORDER BY begin_time)
... but this doesn't work:
ERROR: window function calls cannot be nested
The algorithm is simple: order the rows for a given feature_id by begin_time and check if any end_time > the next begin_time (if any). I suspect there must be an easy way to do this, perhaps with tsrange functions, but can't seem to find it just now.
Calculate total cost based on different rates per hourCount overlapping hours for the first range 00:00-08:00 and multiply with rate 8. returns 16. Count overlapping hours for the second range 08:00-18:00 and multiply with rate 5. Count overlapping hours for the second range 18:00-24:00 and multiply with rate 10.
In PostgreSQL, you can use the OVERLAPS operator to test for overlapping time periods. The function returns true when two time periods (defined by their endpoints) overlap, and false when they do not overlap.
select 'date: time' :: timestamp; select CURRENT_TIMESTAMP :: timestamp; Below is the parameter description of the above syntax are as follows: Select: Select is used to select timestamp value in timestamp syntax.
This can indeed be done using range types.
The following selects all those rows that do have overlapping ranges:
select f1.*
from my_features f1
where exists (select 1
from my_features f2
where tsrange(f2.begin_time, f2.end_time, '[]') && tsrange(f1.begin_time, f1.end_time, '[]')
and f2.feature_id = f1.feature_id
and f2.id <> f1.id);
When you change the condition to NOT EXISTS
you'll find those that don't have any overlapping ranges.
SQLFiddle example: http://sqlfiddle.com/#!15/40b1e/1
tsrange(f2.begin_time, f2.end_time, '[]')
creates a range that includes the upper and lower bounds. You can also create ranges that exclude either one or both.
More details can be found in the manual:
http://www.postgresql.org/docs/current/static/rangetypes.html#RANGETYPES-INCLUSIVITY
The &&
operator checks if the two ranges overlap: http://www.postgresql.org/docs/current/static/functions-range.html
(I just wish Oracle had something fancy like that...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With