SQL Server:使用带有ISOWK参数的DATEPART将周的第一天更改为星期日

时间:2016-03-31 17:40:35

标签: sql sql-server tsql sql-server-2014

我需要为某些日期获得周数。例如,对于2016年1月,它应该是这样的:

[Week Number]
53             <--- for dates from Jan 1 to Jan 2
1              <--- for dates from Jan 3 to Jan 9
2              <--- for dates from Jan 10 to Jan 16
...            <--- etc. 

如你所见,周应从星期日开始。我使用了以下函数来设置开始日期:

SET DATEFIRST 7

这个得到周数:

DATEPART(ISOWK, SOME_DATE)

但我注意到DATEFIRST在使用ISOWK时不会影响结果 - 周总是从星期一开始。

那么,我做错了什么?谢谢!

UPD:

我做了一个功能,看起来效果很好:

CREATE FUNCTION [dbo].[GetWeekNumber]
( 
    @date as DATETIME,
    @offset as INT
)
RETURNS NVARCHAR(100)
    BEGIN 
        DECLARE @weekNumber as int
        DECLARE @year as int

        SET @date = DATEADD(MINUTE, @offset, @date)
        SET @year = DATEPART(year, DATEADD(DAY, 1 - DATEPART(WEEKDAY, @date), CAST(@date AS DATE)))

        IF @@DATEFIRST = 7 
            BEGIN
                SET @date = DATEADD(day, 1, @date)
            END
        SET @weekNumber = DATEPART(ISO_WEEK, @date)
        RETURN concat(@year, ', Week ', right('0' + convert(nvarchar, @weekNumber), 2))
    END

您需要传递日期和时区偏移量(以分钟为单位)。并且在执行此功能之前SET DATEFIRST @startDay(1 - 星期一,7 - 星期日)。例如:

DECLARE @date as DATETIME
SET @date = '2016-01-03 12:00'

SET DATEFIRST 1
SELECT dbo.GetWeekNumber(@date, 0) -- 2015, Week 53

SET DATEFIRST 7
SELECT dbo.GetWeekNumber(@date, 0) -- 2016, Week 01

1 个答案:

答案 0 :(得分:4)

这是设计的。根据{{​​3}}:

  

ISO 8601包括ISO周日期系统,一个编号系统   周。每周与周四发生的年份相关联。   例如,2004年第1周(2004W01)从2003年12月29日星期一开始   到2004年1月4日星期日。

所以ISOWK始终基于星期四,不受DATEFIRST的影响。

要获得所需的结果,只需使用WEEK代替ISOWK

更新:同样来自MSDN:

  

任何一年的1月1日定义了本周的起始编号   datepart,例如:DATEPART(wk,'Jan 1,xxxx')= 1,其中xxxx是   任何一年。

让第1周成为1月3日至9日的唯一方法是使用数学。从DATEPART(wk...)值中减去1,如果结果为0,则将其设为53(或者在您的日期使用DATEADD减去一周)。没有更简单的方法,因为按设计,任何一年的第一周都将是包含1月1日的一周。