MySQL的WEEK()函数需指定mode参数才符合ISO标准,如WEEK(date, 3);SQL Server推荐用DATEPART(isowk, date)避免DATEFIRST影响;PostgreSQL用EXTRACT(week FROM ...)但须注意时区和isoyear配对。

MySQL用WEEK()函数要注意模式(mode)参数
MySQL的WEEK()默认按周日为一周起点、且第1周要求包含1月1日,这和多数人理解的“ISO标准周”不一致。比如2024-01-01是周一,但WEEK('2024-01-01')返回1,而2023-12-31(周日)却返回52——看似合理,但2024-01-07(周日)会返回2,中间没跳过,可一旦遇到跨年边界就容易错乱。
真正对标ISO 8601(周一为每周第一天、第1周必须含当年至少4个周一)的写法是:
SELECT WEEK('2024-01-01', 3); -- 返回1
SELECT WEEK('2023-12-31', 3); -- 返回52
SELECT WEEK('2024-12-30', 3); -- 返回533表示:周一为每周第一天(1),且第1周需含4个以上本周日期(2),合起来是3。常用mode值有:0(默认,周日始,1月1日所在周为第1周)、1(周一始,但第1周仍以1月1日为准)、3(ISO标准)。
SQL Server用DATEPART(WEEK, ...)得配SET DATEFIRST
DATEPART(WEEK, ...)本身不指定周起始日,它依赖会话级设置DATEFIRST。默认DATEFIRST是7(周日),但如果你在代码里没显式设,又换了服务器或连接池配置,结果可能突变。
安全做法是显式控制起始日:
SET DATEFIRST 1; -- 设周一为每周第一天 SELECT DATEPART(WEEK, '2024-01-01'); -- 返回1 SELECT DATEPART(WEEK, '2023-12-31'); -- 返回52
也可以不用SET,改用DATEPART(isowk, ...)直接走ISO逻辑:
SELECT DATEPART(isowk, '2024-01-01'); -- 返回1 SELECT DATEPART(isowk, '2024-12-30'); -- 返回53
isowk不依赖DATEFIRST,也不受语言/区域设置影响,推荐优先用它。
PostgreSQL没有内置WEEK,得靠EXTRACT + timezone调整
PostgreSQL用EXTRACT(week FROM ...),但它返回的是ISO周数(等价于isowk),无需额外配置。但注意:它严格按UTC时间计算,如果字段是带时区的timestamptz,先转成对应时区再提取才准。
例如你存的是北京时间(+08),但直接EXTRACT(week FROM my_time)会按UTC时间算周,导致偏差一天:
-- 错误:没考虑时区偏移 SELECT EXTRACT(week FROM '2024-01-01 00:00:00+08'::timestamptz); -- 实际按2023-12-31 UTC算,可能得52 <p>-- 正确:先转本地时区再抽周<br /> SELECT EXTRACT(week FROM '2024-01-01 00:00:00+08'::timestamptz AT TIME ZONE 'Asia/Shanghai');
另外EXTRACT(year FROM ...)和EXTRACT(week FROM ...)可能跨年不一致:2023-12-31可能是2024年第1周,这时EXTRACT(year FROM ...)是2023,但EXTRACT(week FROM ...)是1——得用EXTRACT(isoyear FROM ...)配对。
跨数据库兼容写法几乎不存在,别硬套
想写一条SQL在MySQL、PostgreSQL、SQL Server里都返回相同ISO周数?基本做不到。各系统对“第几周”的定义、函数名、参数含义、时区处理全都不一样。
实际项目中更稳妥的做法是:
- 业务层统一用
strftime('%G-%V', ...)(SQLite/Python)或DateTime::format('o-W')(PHP)生成ISO周标识,存在数据库里当普通字符串或整数字段 - 查询时只做等值匹配,不依赖数据库实时计算
- 真要在SQL里算,就在应用启动时检测数据库类型,动态拼接对应方言(如MySQL用
WEEK(..., 3),SQL Server用DATEPART(isowk, ...))
最常被忽略的是:周数不是孤立数字,它必须和对应年份一起使用。单独一个“第53周”毫无意义——2023年第53周和2024年第53周差整整一年。所以存储或展示时,2024-W53比单纯53可靠得多。

















