extract可提取year、month、day、hour、minute、second、dow、doy等字段,但各数据库支持不一:postgresql/oracle/bigquery/snowflake原生支持;mysql需用year()等函数;sql server需用datepart()。

EXTRACT 能提取哪些日期字段,各数据库支持是否一致
EXTRACT 不是所有 SQL 方言都原生支持的函数,PostgreSQL、Oracle、Standard SQL(BigQuery、Snowflake)完全支持;MySQL 不支持 EXTRACT,得用 YEAR()、MONTH() 等专用函数;SQL Server 则要用 DATEPART()。别一上来就写 EXTRACT(YEAR FROM order_date),先确认你连的是哪个数据库。
常见可提取的字段包括:YEAR、MONTH、DAY、HOUR、MINUTE、SECOND、DOW(周几,0=Sunday)、DOY(年中第几天)。注意 DOW 和 ISODOW(PostgreSQL)行为不同:前者周日为 0,后者周一为 1。
PostgreSQL 中 EXTRACT 的典型写法和易错点
PostgreSQL 是 EXTRACT 使用最规范的环境,语法统一为 EXTRACT(field FROM timestamp)。最容易出错的是字段名大小写——必须全大写,写成 extract(year from created_at) 会报错:ERROR: function extract(unknown, unknown) does not exist。
-
EXTRACT(YEAR FROM '2023-04-15'::DATE)→ 返回2023(整数类型) -
EXTRACT(MONTH FROM NOW())→ 返回当前月份(如4),不是字符串'04' - 想按“年-月”分组?别直接
GROUP BY EXTRACT(YEAR FROM dt), EXTRACT(MONTH FROM dt),更推荐TO_CHAR(dt, 'YYYY-MM')避免跨年排序混乱
在 BigQuery 或 Snowflake 中用 EXTRACT 处理 TIMESTAMP vs DATE
BigQuery 和 Snowflake 对输入类型敏感:如果字段是 DATE 类型,EXTRACT(HOUR FROM date_col) 会返回 NULL(因为没时间部分);但 EXTRACT(DAY FROM timestamp_col) 没问题。务必核对列的实际数据类型,别只看名字叫 created_at 就默认是 TIMESTAMP。
另一个坑是时区:BigQuery 默认用 UTC 解析 EXTRACT,若原始数据带时区(如 TIMESTAMP("2023-04-15 18:30:00+08")),EXTRACT(HOUR FROM ...) 返回的是 UTC 小时(即 10),不是本地 18 点。需要先用 CAST(... AS TIMESTAMP) AT TIME ZONE "Asia/Shanghai" 调整后再提取。
替代方案:什么时候不该硬用 EXTRACT
单纯取年份或月份时,EXTRACT 没问题;但涉及格式化输出(如 'Q1 2023')、季度计算、或需保留前导零(如 '04'),它就力不从心了。这时候应切换:
- PostgreSQL:优先用
TO_CHAR(order_date, 'YYYY-Q')或date_part('quarter', order_date) - BigQuery:用
FORMAT_DATE('%Y-Q%q', date_col) - 性能敏感场景:对大表做
EXTRACT(YEAR FROM ts)+WHERE过滤,确保ts列上有函数索引(PostgreSQL)或分区(BigQuery),否则全表扫描不可避免
EXTRACT 本质是标量计算函数,它不改变数据分布,也不自动利用分区信息——这点常被忽略,尤其在千万级订单表里按年查询时,慢得莫名其妙,其实只是没建好分区或没重写条件为范围查询。










