- 文档
- 教程
- 知识库
【免费下载链接】til
:memo: Today I Learned
本文围绕 til 仓库 中 PostgreSQL 分类下的实战笔记 different-ways-to-define-an-interval.md,系统梳理interval数据类型的全部常见定义途径。interval用于表示一段离散的时间跨度,是日期运算(date math)的核心工具。读完本文,你将掌握关键字字面量、类型转换、@运算符与make_interval函数这四种定义方式,并能理解它们的等价关系、语法陷阱与适用场景,直接应用到日常 SQL 的时间偏移与筛选逻辑中。
interval 是什么:离散时间跨度的表示
PostgreSQL 的interval类型用于表示一个离散的时间段(a discrete chunk of time),例如"3 天""2 小时 30 分钟""1 年 2 个月"。它不同于timestamp(某个时刻点),也不同于date(某个日历日),它描述的是"多久",因此特别适合做日期运算:给一个时刻加上或减去一段间隔,得到另一个时刻。
这个价值在仓库其他笔记中有大量实战印证:
- using-intervals-to-offset-time.md 展示了用
now() - '2 hours'::interval或now() - interval '2 hours'求"两小时前"的时刻; - idempotent-inserts.md 在幂等插入的去重条件里使用
created_at > (now() - '3 months'::interval)圈定最近三个月; - output-explain-query-plan-in-different-formats.md 用
now() - '1 year'::interval构造一年的时间窗来观察执行计划。
可以看到,interval 一旦和now()、timestamp结合,就能以极简洁的写法完成相对时间运算,这也是本文讨论的四种定义方式最直接的应用场景。
方式一:interval 关键字 + 字符串字面量
最直观的定义方式是用interval关键字紧跟一段字符串,字符串内部使用 PostgreSQL 可识别的单位与数量:
> select interval '3 days'; interval ---------- 3 days (1 row)字符串支持多种自然语言式的组合,例如interval '1 year 2 months 3 days'、interval '2 hours 30 minutes'。PostgreSQL 会解析字符串中形如<数字> <单位>的片段,单位可以是 year、month、day、hour、minute、second 及其复数形式,甚至week。仓库中的 intervals-of-time-by-week.md 就专门演示了周粒度的写法:select '2 weeks'::interval返回14 days,说明周会被统一换算成天数存储。
适用场景:可读性最好,适合手写 SQL、代码评审与临时查询,也是大多数人第一眼能看懂的写法。
方式二:字符串显式转换(::interval)
使用 PostgreSQL 的强制转换语法,把字符串字面量转换为interval类型,效果与方式一完全等价:
> select '3 days'::interval; interval ---------- 3 days (1 row)::interval本质是调用interval的字符串输入函数(interval_in)完成解析,因此'3 days'::interval与interval '3 days'得到的是同一个值。它比关键字写法更灵活的一点是:可以用在任意表达式位置。例如仓库笔记 using-intervals-to-offset-time.md 中:
> select now() - '2 hours'::interval as earlier; earlier ------------------------------- 2015-06-12 21:17:43.678822-05适用场景:需要把常量写进复杂表达式、或让字面量的类型意图在运算式中明确可见时,推荐优先使用::interval,可以避免运算符两侧类型不明确导致的隐式转换意外。
方式三:@运算符(需谨慎的冷门语法)
PostgreSQL 还保留了一个@前缀运算符,可以用于声明 interval:
> select @ 3 days; days ------ 3 (1 row)注意两点:
@ 3 days的结果列名是days,输出值只有数字3,与interval '3 days'的显示形态不同;- 这个语法对空格与格式相当挑剔(原文档称之为 "finicky"),一旦写法不标准很容易触发语法错误,且它依赖上下文中的单位词(如 days)才能被解析。
因此不建议在正式代码中使用。它的存在更多是历史兼容性的体现,日常开发请优先使用前两种方式或make_interval函数。
方式四:make_interval() 函数(参数化构建)
make_interval是 PostgreSQL 提供的专门用于程序化构建 interval 的函数,位于 官方日期时间函数文档 的Interval小节(原文档中亦以此作为参考来源)。它通过具名参数(named arguments)明确指定各个时间分量:
> select make_interval(days => 3); make_interval --------------- 3 days (1 row)函数签名包含 7 个可选参数(均可省略,省略即按 0 处理),按位置顺序为:
| 参数 | 含义 | 默认值 |
|---|---|---|
| years | 年 | 0 |
| months | 月 | 0 |
| weeks | 周 | 0 |
| days | 天 | 0 |
| hours | 小时 | 0 |
| mins | 分钟 | 0 |
| secs | 秒 | 0 |
由于参数众多,具名参数(days => 3)是最清晰、最不容易出错的调用方式。如果使用位置参数,则必须把前面的参数也写全。仓库 intervals-of-time-by-week.md 中给出了位置参数调用的实例:
> select make_interval(0,0,7,0,0,0,0); make_interval --------------- 49 days (1 row)这里的第 3 个参数weeks => 7会被换算为 7 周即 49 天,印证了 interval 内部以"天"为存储单位的换算规则。
适用场景:当间隔的长度在运行时由程序计算得出(例如来自应用层变量或查询参数)时,用make_interval(days => n)这种参数化写法比拼接字符串更安全、更易读,也能完全避免字符串解析的边界问题。
四种方式对比与选择建议
| 定义方式 | 写法示例 | 可读性 | 是否推荐 |
|---|---|---|---|
interval关键字 + 字符串 | interval '3 days' | 最高 | 推荐,日常首选 |
| 字符串强制转换 | '3 days'::interval | 高 | 推荐,表达式内使用 |
@运算符 | @ 3 days | 低,语法挑剔 | 不推荐 |
make_interval()函数 | make_interval(days => 3) | 高,参数化明确 | 推荐,动态构建 |
核心要点:
- 方式一与方式二在语义上完全等价,都是把字符串交给 interval 的输入解析器,区别只在写法;
@运算符仅作为冷门兼容语法存在,实际项目建议避开;make_interval支持年、月、周、天、时、分、秒七个分量的自由组合,是最适合动态构建间隔的手段;- 无论用哪种方式定义,得到的都是同一个
interval值,可直接参与now() - interval之类的日期运算。
以上四种方式也补充了仓库中 intervals-of-time-by-week.md 与 using-intervals-to-offset-time.md 两篇相关笔记的实践细节,可配合阅读,形成对 PostgreSQL 时间跨度处理的完整认识。
- 文档
- 教程
- 知识库
【免费下载链接】til
:memo: Today I Learned
相关推荐
PostgreSQL 按周构建时间区间:'2 weeks' 字面量与 make_interval 周参数详解
PostgreSQL 按周构建时间区间:'2 weeks' 字面量与 make_interval 周参数详解 在 PostgreSQL 中做日期计算时,最常用的
文档教程知识库Carbon 语言字面量表达式详解:值驱动类型、iN/uN/fN 类型字面量与字符语义
Carbon 语言字面量表达式详解:值驱动类型、iN/uN/fN 类型字面量与字符语义 本文围绕 docs/design/expressions/literal
编程语言编译器标准库Flax flax.struct 模块详解:为 JAX 函数式变换构建自定义 PyTree 数据类
Flax flax.struct 模块详解:为 JAX 函数式变换构建自定义 PyTree 数据类 本篇围绕 flax.struct 包的 API 文档展开,系
人工智能深度学习机器学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考