table (simplified)
Table "public.events"
Column | Type | Modifiers
------------------+-----------------------------+--------------------------------------------------------
id | integer | not null default nextval('events_id_seq'::regclass)
duration | integer | not null
start_at | timestamp without time zone |
Indexes:
"events_pkey" PRIMARY KEY, btree (id)
"my_idx" gist (tsrange(start_at, end_at(events.*), '[)'::text))
function
CREATE FUNCTION end_at(rec events)
RETURNS timestamp without time zone
IMMUTABLE
LANGUAGE SQL
AS $$
SELECT $1.start_at + ($1.duration * ('00:00:01'::interval));
$$;
what I am already doing successfully
The index is used for queries like this:
-- check if current time is within the start and end times
-- of event
where localtimestamp <@ tsrange(start_at, events.end_at, '[)')
And it works well.
what I want to do
I want to query for events where the current time is after they have ended. Ways I know of how to do this:
where tsrange(localtimestamp, localtimestamp, '[]') >> tsrange(start_at, events.end_at, '[)')
. I'm pretty sure this is the semantics I want, andexplain analyze
says it's using the index, but it's a bit ugly and I'm wondering if there's a better way to express this (and also am vaguely uncertain it's the semantics I want, as I am new to ranges).where localtimestamp > upper(tsrange(start_at, events.end_at, '[)'))
+ a btree index onupper(tsrange(start_at, events.end_at, '[)'))
. This will work well, but requires keeping another index around.where localtimestamp > events.end_at
. + a btree index onevents.end_at
. Same situation as above.
Is there a more elegant (or correct) way to achieve the first bullet point above?
Any other ideas for how to go about this?