很多方法。
在我的示例中使用列名 "ts"。 timestamp 列的“日期”会产生误导。
1.
转换为date。 (这里我们需要 date 类型。在其他表达式中,date_trunc() 也一样。)。然后在减去区间1 second之前加上1(integer):
SELECT ts::date + 1 - interval '1 sec' AS last_sec_of_day
2.
添加一个单个间隔'1 day - 1 sec'。不需要两个操作,Postgres interval input 允许单个表达式。
SELECT ts::date + interval '1 day - 1 sec' AS last_sec_of_day
3.
更简单,将所需的时间组件添加到日期:
SELECT ts::date + time '23:59:59' AS last_sec_of_day
4.
但是,xxxx-xx-xx 23:59:59 不是“一天的结束”。 Postgres timestamp data type(目前,但不太可能更改)以微秒级分辨率存储值。
一天中可能的最新时间戳是xxxx-xx-xx 23:59:59.999999:
SELECT ts::date + interval '1 day - 1 microsecond' AS last_ts_of_day
5.
等效:
SELECT ts::date + time '23:59:59.999999' AS last_ts_of_day -- or interval
最后一个表达式应该是除了正确之外最快的。
6.
然而,更好的方法通常是以第二天的开始作为唯一的上限,它不依赖于实现细节,甚至更简单生成:
SELECT ts::date + 1 AS next_day
7.
第二天的实际第一个时间戳:
SELECT date_trunc('day', ts) + interval '1 day' AS next_day_1st_ts
至少从 Postgres 8.4 开始,所有版本都可以工作。 Postgres 13 中的演示:
db小提琴here