首页/数据/SQL 速查/EXTRACT 提取日期字段
函数速查60 条

EXTRACT 提取日期字段

从日期时间中取出年/月/日/时/分/周等字段:标准写法 EXTRACT(unit FROM expr),MySQL 另有 YEAR()/MONTH() 等简写。

SQL 速查数据更新于 2026-10-13

EXTRACT 是什么

EXTRACT(unit FROM expr) 从日期时间值里取出单个字段:年、月、日、时、分、秒、周、季度。这是 SQL 标准写法,MySQL 8 与 PostgreSQL 都支持;MySQL 另有 YEAR()、MONTH() 这类简写函数,PostgreSQL 则扩展了 DOW、ISODOW、EPOCH 等单位。

基本信息

通用语法EXTRACT(YEAR FROM created_at)
常用单位YEAR / MONTH / DAY / HOUR / MINUTE / SECOND / QUARTER / WEEK
MySQL 简写YEAR()、MONTH()、DAY()、HOUR()、MINUTE()、SECOND()、QUARTER()
PostgreSQL 扩展DOW(周日为 0)、ISODOW(周一为 1)、DOY、EPOCH
返回类型PostgreSQL 返回 numeric;MySQL 返回整数
索引影响对列做 EXTRACT 之后再过滤,普通索引无法使用

拆出年月日时

拆出年月日时
SELECT EXTRACT(YEAR  FROM o.created_at) AS y,
       EXTRACT(MONTH FROM o.created_at) AS m,
       EXTRACT(DAY   FROM o.created_at) AS d,
       EXTRACT(HOUR  FROM o.created_at) AS h
FROM orders o
WHERE o.created_at >= '2024-06-01'   -- 先按列过滤,保住索引
  AND o.created_at <  '2024-07-01'
ORDER BY y, m, d, h;                 -- 取字段是为了分组展示,不是为了过滤

简写与扩展单位

简写与扩展单位
-- MySQL 简写,可读性更好
SELECT YEAR(created_at), MONTH(created_at), DAYOFMONTH(created_at) FROM orders;

-- PostgreSQL 扩展单位:季度、ISO 周内日、自 1970 起的秒数
SELECT EXTRACT(QUARTER FROM ts) AS q,
       EXTRACT(ISODOW  FROM ts) AS iso_dow,
       EXTRACT(EPOCH   FROM ts) AS epoch_secs
FROM t;   -- 注意 EPOCH 返回 numeric,序列化前按需 CAST

常用单位对照

单位含义说明
YEAR四位年份两库行为一致
MONTH月份 1 到 12两库行为一致
QUARTER季度 1 到 4MySQL 与 PG 都支持
WEEK周序号口径随参数变化,跨系统前先对齐
DOW / ISODOW周内日PG 单位;MySQL 用 DAYOFWEEK、WEEKDAY
EPOCH自 1970 起的秒数PG 返回 numeric

典型使用场景

  • 按年月出趋势:月度汇总、同比环比的基础
  • 按小时看流量分布,定位业务高峰
  • 按季度汇总,匹配财报与考核口径
  • 按周内日分析,比较周末与工作日的差异
  • 时间戳与日期互转前先拆解字段,便于分组展示
  • 排查脏数据:看是否存在年份异常的记录
  • 把年、月拆成两列导出,方便下游直接做透视
  • 跨年周统计:先确定按自然年还是按 ISO 周归属年份
WEEK 的编号口径最容易出错:PostgreSQL 的 EXTRACT(WEEK) 是 ISO 周(周一为一周开始,第 1 周含 1 月 4 日);MySQL 的 WEEK() 结果受 default_week_format 影响。跨系统对比周数据前先确认口径。
按周统计前先定义清楚业务口径:自然周(周一到周日)还是 ISO 周,跨年那一周归到哪一年。用 EXTRACT(WEEK) 与用年加周序号组合的结果不同,口径要写进注释。
字段本身带时区时,先 AT TIME ZONE 换算到业务时区再取字段,否则东八区凌晨的数据会被归到前一天,日报与流水对不上。
WHERE EXTRACT(YEAR FROM created_at) = 2024 会让索引完全用不上,必须改写成范围条件:created_at >= '2024-01-01' AND created_at < '2025-01-01'。

易错点

  • 在 WHERE 里对索引列做 EXTRACT:索引失效退化为全表扫描,改写成范围条件
  • 跨库直接用周序号:MySQL 的 WEEK 与 PG 的 ISO 周编号不同,统计结果可能整体差一周
  • 把 EXTRACT 的结果当字符串拼接:返回的是数值(PG 为 numeric),拼接前先 CAST
  • 忽略时区直接取字段:带时区的时间戳先 AT TIME ZONE 换算,否则取到的是存储时区的年月日
  • 跨年周用年加周序号拼接:跨年第 1 周会被算进上一年,与业务口径不符,先确认归属规则

数据来源与参考

  • MySQL 8.0 Reference Manual · EXTRACT
  • PostgreSQL Documentation · Date/Time Functions and Operators
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌