mysql中weekday()返回0=周一更符合常规认知,dayofweek()返回1=周日;postgresql的extract(dow)同mysql的dayofweek();sqlite用strftime('%w');跨库建议应用层处理并注意时区。

MySQL 中用 DAYOFWEEK() 或 WEEKDAY() 获取星期几
MySQL 不直接返回“周一”“周二”这种中文名,而是返回数字,但规则容易混淆:DAYOFWEEK() 返回 1=周日、2=周一…7=周六;WEEKDAY() 返回 0=周一、1=周二…6=周六。选哪个取决于你是否把周日当一周起点。
常见错误是查出数字后直接映射成“1→周一”,结果发现对不上——那大概率用了 DAYOFWEEK() 却按周一为 1 来理解。
- 要兼容常规认知(周一为第一天),优先用
WEEKDAY(时间字段) - 需要中文名?用
CASE WHEN手动映射:SELECT CASE WEEKDAY(created_at) WHEN 0 THEN '周一' WHEN 1 THEN '周二' WHEN 2 THEN '周三' WHEN 3 THEN '周四' WHEN 4 THEN '周五' WHEN 5 THEN '周六' WHEN 6 THEN '周日' END AS week_day FROM orders; -
WEEKDAY()支持DATETIME、TIMESTAMP和日期字符串,自动忽略时分秒部分(即只看日期)
PostgreSQL 中用 EXTRACT(DOW FROM ...) 或 TO_CHAR(..., 'Day')
PostgreSQL 的 EXTRACT(DOW FROM 时间字段) 返回 0=周日、1=周一…6=周六,和 MySQL 的 DAYOFWEEK() 一致,不是直觉上的“周一=0”。如果想输出中文或英文星期名,TO_CHAR() 更直接。
- 获取数字(注意:0 是周日):
EXTRACT(DOW FROM created_at) - 获取本地化星期名(依赖数据库
lc_time设置):TO_CHAR(created_at, 'Day')→ 返回带空格的字符串如'Monday ' - 去空格 + 小写处理更稳妥:
TRIM(TO_CHAR(created_at, 'Day')),再配合CASE转中文也行 - 若字段是
UNIX timestamp(整数秒),先转成TIMESTAMP:TO_TIMESTAMP(created_at)
SQLite 中没有内置星期函数,得靠 strftime()
SQLite 的 strftime() 是万能解法,但格式符容易记混:%w 返回 0=周日、1=周一…6=周六;%W 是全年第几周(以周一为每周开始),别用错。
- 最常用写法:
strftime('%w', created_at)→ 得到数字 - 要中文名?同样靠
CASE映射,但注意 SQLite 的CASE不支持直接在SELECT里写多行缩进,建议写成单行或建视图 - 时间字段必须是 SQLite 认可的日期格式(如
'2024-05-20 14:30:00'或unixepoch格式),否则strftime()返回NULL - 如果是整数时间戳(秒级),加参数
'unixepoch':strftime('%w', created_at, 'unixepoch')
跨数据库可移植写法?别硬套,优先明确业务语义
没有一行 SQL 能在所有数据库返回“周一”字符串——函数名、参数顺序、周起始日定义、本地化支持全都不统一。强行封装成通用函数反而增加维护成本。
- 如果只是报表展示,各库分别写
CASE + 原生函数最稳 - 如果逻辑在应用层,建议把时间戳传给程序,用 Python 的
.strftime('%A')或 JavaScript 的date.toLocaleDateString('zh-CN', { weekday: 'long' })处理,语义清晰且可控 - 特别注意:不同数据库对“本周第一天”的定义可能影响周统计(比如
WEEK()函数),查周几只是表层,背后常连着周汇总逻辑,得同步确认周边界
真正容易被忽略的,是时间字段的时区。created_at 存的是 UTC 还是本地时间?strftime() 和 EXTRACT() 都不会自动时区转换,错一时区,星期就差一天。










