我正在使用
PostgreSQL 8.4
。我有表my_tbl
的一列,其中包含日期(timestamp without timezone
)。例如:
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
如何编写以以下格式返回所有日期的 SQL 查询:
xxxx-xx-xx 23:59:59
那是每个日期都会被设置为一天的结束。
很多方式。
我们说的是
timestamp
类型。 Postgres 中的首选类型是timestamptz
。注意区别!参见:
在我的例子中使用列名
ts
。时间戳列的“日期”会产生误导。
ts::date + 1 - interval '1 sec'
投射到
date
,加integer '1'
,然后减去interval '1 second'
.
加法 date + int 是唯一实际需要类型
date
的情况。此答案中的所有其他表达式同样适用于 date_trunc()
- 甚至更快。
ts::date + interval '1 day - 1 sec'
date_trunc('day', ts) + interval '1 day - 1 sec'
Postgres interval input 允许具有多个时间单位的单个表达式。无需两次操作。
date_trunc('day', ts) + interval '23:59:59'
更简单的是,将所需的时间组件添加到日期(或一天的开始)。
date_trunc('day', ts) + time '23:59:59'
与类型相同
time
.
xxxx-xx-xx 23:59:59
是not“一天结束”。 Postgres timestamp
数据类型(目前,不太可能改变)以微秒分辨率存储值。一天的最新可能时间戳是xxxx-xx-xx 23:59:59.999999
.
date_trunc('day', ts) + interval '1 day - 1 microsecond'
date_trunc('day', ts) + interval '23:59:59.999999'
date_trunc('day', ts) + time '23:59:59.999999'
这最后一个表达式应该是除了正确之外最快.
通常,在第二天开始时作为 exclusive upper bound 操作是更好的方法。不依赖于实现细节,生成起来更简单。
ts::date + 1 -- returns date!
date_trunc('day', ts) + interval '1 day' -- returns timestamp
至少从 Postgres 8.4 开始,所有版本都可以工作。 Postgres 15 中的演示:
取日期,截断它,加一天减一秒:
select date_trunc('day', date) + interval '1 day' - interval '1 second'
如果要更改表中的数据,可以将逻辑放在
update
中。
当然也可以加上24*60*60 - 1秒:
select date_trunc('day', date) + (24*60*60 - 1) * interval '1 second'
但这似乎不太优雅。