SQL Server 2012中按周一为周起始从日期提取周数和日数
拆解SQL Server中按月计算周数的代码&提取周内日数方法
嗨,我来帮你把这段SQL代码拆解开,彻底搞懂它的逻辑,同时告诉你怎么提取以周一为起始的周内日数~
一、按月计算周数的代码逻辑拆解
你拿到的代码是:
SELECT DATEDIFF(week, DATEADD(week, DATEDIFF(week, 0, DATEADD(month, DATEDIFF(month, 0, @date), 0)), 0), @date - 1) + 1
我们从内到外一步步拆解每部分的作用:
DATEDIFF(month, 0, @date)- 这里的
0代表SQL Server的基准日期1900-01-01,这个函数计算从基准日到@date所在月份的总月数。比如@date='2019-05-01'时,结果是1429(1900年1月到2019年5月共1429个月)。
- 这里的
DATEADD(month, 上面的结果, 0)- 把第一步得到的月数加回基准日,得到
@date所在月份的第一天。比如例子中就是2019-05-01。
- 把第一步得到的月数加回基准日,得到
DATEDIFF(week, 0, 当月第一天)- 计算从基准日到当月第一天的周数间隔。注意SQL Server默认周起始是周日,但这段代码的目标是把周起始改成周一,所以这一步是为了找到当月第一天所在周的周一。
DATEADD(week, 上面的周数, 0)- 把第三步的周数加回基准日,得到当月第一天所在周的周一。比如2019年5月1日是周三,它所在周的周一是2019-04-29,这一步就得到这个日期。
DATEDIFF(week, 这个周一, @date - 1)- 计算从这个周一到
@date前一天的周数差。例子中@date-1是2019-04-30,和周一2019-04-29的周数差是0。
- 计算从这个周一到
最后
+1- 因为周数是从1开始计数的,差为0时代表是第1周,加1后就得到正确的周数(例子中结果为1,符合你的需求)。
整个逻辑的核心是:先找到当月第一天所在周的周一作为计算起点,再计算@date距离这个起点的周数,最后调整为从1开始的计数。
二、提取以周一为起始的周内日数
要得到以周一为第1天、周日为第7天的日数,有两种简单方法:
方法1:使用ISO_WEEKDAY(推荐)
SQL Server的ISO_WEEKDAY函数本身就是以周一为起始日的:周一=1,周二=2,…,周日=7。直接用它就行:
SELECT DATEPART(iso_weekday, @date) AS 日数
比如@date='2019-05-01'时,结果就是3,完美符合你的例子。
方法2:调整默认weekday的结果
如果你的SQL Server版本不支持ISO_WEEKDAY(不过2012是支持的),可以调整默认的weekday结果(默认周日=1,周一=2…周六=7):
SELECT (DATEPART(weekday, @date) + 5) % 7 + 1 AS 日数
计算逻辑:把周日(1)转成7,周一(2)转成1,以此类推。代入例子中的@date='2019-05-01',DATEPART(weekday, @date)是4,(4+5)%7+1=9%7+1=2+1=3,结果正确。
内容的提问来源于stack exchange,提问作者user3693634
相关产品推荐
相关产品推荐

