Als u daadwerkelijk een kolom van het type timestamp
. heeft en interpreteer het (in delen) afhankelijk van de huidige tijdzone, en deze tijdzone kan variëren, dan is een index over het algemeen onmogelijk . U kunt alleen een index bouwen op IMMUTABLE
gegevens ...
Na update:
Om deze vragen te beantwoorden:
- Welke reserveringen beginnen "vandaag"?
- Welke reserveringen hebben startdata in de toekomst?
- Welke reserveringen hebben een startdatum in het verleden?
... je het beste een timestamp with time zone
. Gewoon een date
is niet precies genoeg.
Zolang we alleen geïnteresseerd zijn in het lokale "vandaag" (zoals gedefinieerd door de huidige tijdzone ), doen we niet moet de tijdzone expliciet opslaan. Het maakt ons niet uit waar ter wereld het gebeurt, we hebben alleen een absolute tijd nodig om mee te vergelijken.
Om vervolgens "vandaag" reserveringen te krijgen:
SELECT *
FROM reservations
WHERE start_on::date = current_date;
Maar dit is niet sargable
omdat start_on::date
is een afgeleide uitdrukking en we kunnen hier ook geen functionele index voor bouwen (zonder vuile trucs) omdat de uitdrukking afhangt van de huidige tijdzone en niet IMMUTABLE
is .
In plaats daarvan , vergelijk met het begin en einde van "onze" dag in UTC-tijd:
SELECT *
FROM reservations
WHERE start_on >= current_date::timestamptz
AND start_on < (current_date + 1)::timestamptz; -- exclude upper border
Nu kan deze eenvoudige index de zoekopdracht ondersteunen:
CREATE INDEX ON reservations (start_on);
Demo
SQL Fiddle heeft geen ATM. Hier is een kleine demo om het te begrijpen:
CREATE TEMP TABLE reservations (
reservation_id serial
, start_on timestamptz NOT NULL
, time_zone text); -- we don't need this
INSERT INTO reservations (start_on, time_zone) VALUES
('2014-04-09 01:00+02', 'Europe/Vienna')
, ('2014-04-09 23:00+02', 'Europe/Vienna')
, ('2014-04-09 01:00+00', 'UTC') -- the value is independent of the time zone
, ('2014-04-09 23:00+00', 'UTC') -- only display depends on current time zone
, ('2014-04-09 01:00-07', 'America/Los_Angeles')
, ('2014-04-09 23:00-07', 'America/Los_Angeles');
SELECT start_on, time_zone
, start_on::timestamp AS local_ts
, start_on AT TIME ZONE time_zone AS ts_at_tz
, current_date::timestamptz AS lower_bound
, (current_date + 1)::timestamptz AS upper_bound
FROM reservations
WHERE start_on >= current_date::timestamptz
AND start_on < (current_date + 1)::timestamptz;
Meer uitleg en links hier:
Tijdzones volledig negeren in Rails en PostgreSQL