Answer for timestamp
You need to understand the nature of the timestamp without time zone and timestamp with time zone data types (names can spoof). If you do not, read this first:
- Ignoring Time Zones in General in Rails and PostgreSQL
The AT TIME ZONE construct converts your timestamp to timestamptz , which almost certainly means a wrong move :
where eventtime at time zone 'CET' between '2015-06-16 06:00:00' and '2015-06-17 06:00:00'
First , it kills performance. Using AT TIME ZONE to eventtime makes the expression not sargable . Postgres cannot use a simple index on eventtime . But even without an index, expressed expressions are cheaper. Specify the boundaries adjusted for the values ββin the table, so you do not need to manipulate each row.
You could compensate for the corresponding expression index, but this is probably just a misunderstanding and a misnomer.
What happens in this expression?
AT TIME ZONE 'CET' converts the timestamp eventtime to timestamptz by adding the time zone offset of the current time zone. This takes into account DST (daylight saving time), so you get a different offset for winter timestamps. Basically you get the answer to the question:
What is the absolute time (UTC timestamp) when a given time zone sees a given timestamp?
When the result is displayed to the user, it becomes the corresponding time stamp for the current time zone of the session with the added time zone offset. (May or may not be the same as the one used in the expression).
The string literals on the right side do not have any data type for them, so they assume that the type is derived from the destination in the expression. Since we effectively have timestamptz , both of them are passed to timestamptz , assuming the current time zone of the session.
Give me a UTC timestamp for a point in time when local time looks like a given timestamp.
The offset depends on the DST rules.
In short , if you work with the same time zone everywhere: CET or 'Europe/Berlin' , the same for today's timestamps, but not for historical or (possibly) future ones, you can just cut the croup.
second problem with the expression: BETWEEN almost always does not match the timestamp values. Details:
- Optimize the report on the current date .
- Find overlapping date ranges in PostgreSQL
SELECT date_trunc('hour', eventtime) AS hour , count(DISTINCT serialnumber) AS ct
now() is a Postgres implementation of the CURRENT_TIMESTAMP SQL standard. Both return timestamptz (not timestamp !). You can use either.
now()::date equivalent to CURRENT_DATE . Both depend on the setting of the current time zone.
You should have a form index :
CREATE INDEX foo ON t_el_eventlog(sourceid, eventtime)
Or, to allow viewing only by index:
CREATE INDEX foo2 ON t_el_eventlog(sourceid, eventtime, serialnumber)
If you work in different time zones, everything becomes more complicated, and you should use timestamptz for everything.
Alternative for timestamptz
Prior to updating the question, it seemed that time zones mattered. When working with different time zones, βtodayβ is the functional dependence of the current time zone. People tend to forget about it.
To simply work with the current session time zone, use the same query as above. If they run in a different time zone, the results are actually incorrect. (Also applies to the above.)
To guarantee the correct result for a given time zone ("Europe / Berlin" in your case), regardless of the setting of the current session time zone, use this expression instead:
((now() AT TIME ZONE 'Europe/Berlin')::date - interval '18 hours') AT TIME ZONE 'Europe/Berlin' -- 2nd time to convert back
Keep in mind that the AT TIME ZONE construct returns a timestamp for entering timestamptz and vice versa.
As mentioned at the beginning, all the details are here:
- Ignoring Time Zones in General in Rails and PostgreSQL