I'm using PostgreSQL 8.4
. I have a column of the table my_tbl
which contains dates (timestamp without timezone
). For instance:
date
-------------------
2014-05-27 12:03:20
2014-10-30 01:20:03
2013-10-19 16:34:34
2013-07-10 15:24:26
2013-06-24 18:15:06
2012-07-14 07:09:14
2012-05-13 04:46:18
2013-01-04 21:31:10
2013-03-26 10:17:02
How to write an SQL query which returns all dates in the format:
xxxx-xx-xx 23:59:59
That's every date will be set to the end of the day.
Take the date, truncate it, add one day and subtract one second:
select date_trunc('day', date) + interval '1 day' - interval '1 second'
You can put the logic in an update
if you want to change the data in the table.
Of course, you can also add 24*60*60 - 1 seconds:
select date_trunc('day', date) + (24*60*60 - 1) * interval '1 second'
But that seems less elegant.
Many ways.
I wouldn't call a timestamp
column "date"
, that's misleading. It's also a reserved word in standard SQL and a basic type name in Postgres and shouldn't be used as identifier at all. Using column name ts
instead.
1. Cast to date. Shorter than date_trunc()
. Then add 1
(integer
) before you subtract the interval 1 second
:
ts::date + 1 - interval '1 sec' AS last_sec_of_day FROM my_tbl;
2. Add an interval '1 day - 1 sec'
. No need for two operations, Postgres interval input can take both in one step:
ts::date + interval '1 day - 1 sec' AS last_sec_of_day
3. Simpler yet, add the desired time component to the date:
ts::date + time '23:59:59' AS last_sec_of_day
4. However, is not the end of the day. The Postgres xxxx-xx-xx 23:59:59
timestamp
data type (currently, but unlikely to change) stores values with microsecond resolution.
The latest possible timestamp for a day is xxxx-xx-xx 23:59:59.999999
:
ts::date + interval '1 day - 1 microsecond' AS last_ts_of_day
5. Equivalent:
ts::date + time '23:59:59.999999' AS last_ts_of_day -- or interval, same result
This last expression should be fastest besides being correct.
6. However, the superior approach typically is to operate with the start of the next day as exclusive upper border, which does not depend on an implementation detail and is even simpler to generate:
ts::date + 1 AS next_day_1st_ts
7. The actual first timestamp of the next day:
date_trunc('day', ts) + interval '1 day' AS next_day_1st_ts
All work in any version since Postgres 8.4 or even longer. Demo in Postgres 12:
db<>fiddle here
来源:https://stackoverflow.com/questions/27689384/how-to-get-the-end-of-a-day