41 日期函数与 COALESCE
PostgreSQL 提供了丰富的日期和时间运算。date_trunc 将时间截断到指定精度;extract 提取单个字段;interval 允许你加减时间间隔;date_part、age、to_char、to_date 涵盖其余需求。COALESCE 虽然并非日期专用,但很适合与日期逻辑搭配,用来为可能为空的值指定默认值。
本章要点
current_date、current_timestamp、now()、clock_timestamp()date_trunc(unit, ts):截断到年、月、日、小时等精度extract(field FROM ts):提取年、月、星期几等字段interval运算与格式化- 使用
COALESCE为 NULL 提供回退值
示例
date_trunc('month', ts) 是分析中按月“分桶”的标准方式。结果是该月第一天午夜的 timestamp(或 timestamptz)。使用 extract(isodow FROM ts) 按星期几分组,使用 date_trunc('week', ts) 按日历周分组,或者使用 date_bin(PostgreSQL 14+)划分固定宽度的时间桶。
extract 返回 numeric(较早版本中为 double precision)。dow 字段以星期日为 0;isodow 以星期一为 1(与 ISO 8601 一致)。如果拿不准,isodow 更符合大多数“星期一是一周的开始”的约定。
age(end, start) 返回按年、月、日归一化的时间间隔,适合用于显示(“3 年、2 个月”)。如果需要原始差值,可以直接减去两个 timestamptz 值,得到以日、小时和秒表示的时间间隔。
COALESCE 按从左到右的顺序检查参数,并返回第一个非 NULL 值。它是处理“默认值”的标准工具:COALESCE(user.display_name, user.email, 'Anonymous')。
运行示例
运行方式:
常见陷阱
now()返回事务开始时间。在长事务中,每次调用都会返回相同的值。需要真实的挂钟时间时,请使用clock_timestamp()。- 混用
timestamp和timestamptz时,会静默使用会话的时区。请明确指定:在类型转换或显示时使用at time zone 'UTC',并尽可能将数据存储为timestamptz。 date_trunc返回与输入相同类型的值——date_trunc('day', timestamptz)返回的是timestamptz,而不是date。如果需要date,请进行类型转换。- 在 PostgreSQL 17 中,
extract(epoch FROM ts)返回自 Unix 纪元起经过的numeric秒数;date_part('epoch', ts)返回double precision。与使用 Unix 时间的代码互操作时,这一点很有用。 COALESCE使用短路求值,因此,当更早的参数非 NULL 时,后续参数中的有副作用表达式不会被求值。
对于“下个月的第一天”,可以使用 date_trunc('month', current_date) + interval '1 month'。对于“本月最后一天”,可以使用 date_trunc('month', current_date) + interval '1 month' - interval '1 day'。这些习惯用法在报表查询中随处可见。
计算当前年份的第一天(date_trunc('year', current_date))。将时间戳格式化为 ISO 8601:to_char(current_timestamp, 'YYYY-MM-DD"T"HH24:MI:SSOF')。在针对 tasks_example 的 SELECT 查询中使用 COALESCE,显示 due_at 或 ’no deadline’。
下载
SQL 文件:date-functions-and-coalesce.sql · 全部示例文件 · 准备工作