SQL Server: измените первый день недели на воскресенье, используя DATEPART с параметром ISOWK

Мне нужно получить номера недель для некоторого набора дат. Например, для января 2016 года это должно быть примерно так:

[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

person Eugene Karashevich    schedule 31.03.2016    source источник


Ответы (1)


Это сделано намеренно. Согласно MSDN:

ISO 8601 включает систему даты недели ISO, систему нумерации недель. Каждая неделя связана с годом, в который приходится четверг. Например, первая неделя 2004 г. (2004W01) проходила с понедельника 29 декабря 2003 г. по воскресенье 4 января 2004 г.

Таким образом, ISOWK всегда основывается на четвергах и не зависит от DATEFIRST.

Чтобы получить желаемый результат, просто используйте WEEK вместо ISOWK.

ОБНОВЛЕНИЕ: Также из MSDN:

1 января любого года определяет начальный номер для части даты недели, например: DATEPART (wk, '1 января, xxxx') = 1, где xxxx - любой год.

Единственный способ сделать неделю № 1 3–9 января - использовать математику. Вычтите единицу из значения DATEPART(wk...), и если результат 0, сделайте его 53 (или просто используйте DATEADD на вашей дате, чтобы вычесть неделю). Нет более простого способа, так как по замыслу первая неделя любого года будет неделей с 1 января.

person Tab Alleman    schedule 31.03.2016
comment
Я также пробовал WEEK, он работает правильно с DATEFIRST, но это не то, что мне нужно, например, номер недели для Jan 1 будет 1, но мне нужна следующая нумерация (как я писал выше): 1,2 января - ›Неделя 53 , 3 ... 9 января - ›Неделя 1, 10 ... 16 января -› Неделя 2 - person Eugene Karashevich; 31.03.2016
comment
Спасибо за совет! Я обнаружил, что это можно сделать, просто добавив день к дате - вы можете увидеть функцию и пример в обновлении моего ответа. - person Eugene Karashevich; 01.04.2016