在SQL开发场景中,获取指定日期所在星期的起始日期是高频需求,比如统计周维度的业务数据、生成周报表时都需要用到这个逻辑。不同数据库的内置日期函数语法存在差异,实现方式也各有不同,下面分别介绍主流数据库的实现方案。

MySQL中获取星期起始日期
MySQL的WEEKDAY()函数返回日期对应的星期索引,默认周一是0,周日是6,结合DATE_SUB()函数可以计算起始日期。如果需要自定义星期的起始日,可以通过WEEK()函数的模式参数调整。
默认周一为起始日
以下代码获取当前日期所在星期的周一日期:
-- 获取当前日期所在星期的周一(默认周一为星期起始日)
SELECT
DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) AS week_start_date;
自定义星期起始日
如果需要周日为起始日,可以使用DAYOFWEEK()函数,该函数返回1-7对应周日到周六:
-- 获取当前日期所在星期的周日(周日为星期起始日)
SELECT
DATE_SUB(CURDATE(), INTERVAL (DAYOFWEEK(CURDATE()) - 1) DAY) AS week_start_date;
SQL Server中获取星期起始日期
SQL Server的DATEPART()函数可以获取日期的星期信息,默认设置下周日是1,周六是7,也可以通过SET DATEFIRST修改星期的起始日配置。
默认周日为起始日
以下代码获取当前日期所在星期的周日日期:
-- 获取当前日期所在星期的周日(默认周日为星期起始日)
DECLARE @current_date DATE = GETDATE();
SELECT
DATEADD(DAY, 1 - DATEPART(WEEKDAY, @current_date), @current_date) AS week_start_date;
设置周一为起始日
通过SET DATEFIRST 1可以将周一设置为星期起始日,此时DATEPART(WEEKDAY)返回1对应周一:
-- 设置周一为星期起始日,获取当前日期所在星期的周一
SET DATEFIRST 1;
DECLARE @current_date DATE = GETDATE();
SELECT
DATEADD(DAY, 1 - DATEPART(WEEKDAY, @current_date), @current_date) AS week_start_date;
PostgreSQL中获取星期起始日期
PostgreSQL的EXTRACT()函数可以提取日期的星期信息,DOW参数返回0-6对应周日到周六,ISODOW参数返回1-7对应周一到周日,使用DATE_TRUNC()函数可以直接截断到星期的起始位置。
ISO标准周一为起始日
ISO标准中一周的起始日是周一,使用ISODOW参数配合DATE_TRUNC()可以快速获取:
-- 获取当前日期所在星期的周一(ISO标准,周一为起始日)
SELECT
DATE_TRUNC('week', CURRENT_DATE) AS week_start_date;
自定义周日为起始日
如果需要周日为起始日,可以通过EXTRACT(DOW)计算偏移量:
-- 获取当前日期所在星期的周日(周日为起始日)
SELECT
CURRENT_DATE - EXTRACT(DOW FROM CURRENT_DATE)::INT AS week_start_date;
不同数据库实现对比
以下是三种数据库获取星期起始日期的核心逻辑对比:
| 数据库类型 | 核心函数 | 默认星期起始日 | 自定义起始日方式 |
|---|---|---|---|
| MySQL | WEEKDAY(), DAYOFWEEK(), DATE_SUB() | 周一 | 使用DAYOFWEEK()替换WEEKDAY() |
| SQL Server | DATEPART(), DATEADD(), SET DATEFIRST | 周日 | 执行SET DATEFIRST 1设置周一为起始日 |
| PostgreSQL | EXTRACT(), DATE_TRUNC() | 周一(ISO标准) | 使用EXTRACT(DOW)计算周日偏移量 |
注意事项
- 不同数据库的星期索引规则不同,使用前需要先确认函数的返回值定义,避免计算错误。
- SQL Server的
SET DATEFIRST设置是会话级别的,会影响当前连接后续的所有星期相关计算,使用时需要注意作用范围。 - 如果业务需要兼容多种数据库,建议封装统一的日期计算函数,避免重复编写适配逻辑。