SQL Server: получите датутифф за недели ISO

Лучшую половину дня потратил на то, чтобы понять это.

Я хочу получить datediff из двух дат на основе их недели ISO.

Вот мой код:

SET DATEFIRST 1 ;   

DECLARE @A date, @B date;

SET @A = '20180829'; -- August 29th
SET @B = '20180902'; -- September 2nd

SELECT DATEDIFF(WW, @A, @B )

Если вы проверите: http://whatweekisit.org/ (35 неделя, 2018 год), вы увидите, что он работает 27 августа по 2 сентября.

Приведенный выше код вернет DateDiff = 1, который должен быть 0. Попытка запустить DateDiff на неделе ISO возвращает следующую ошибку:

Datepart iso_week не поддерживается функцией date dateiff

Я пробовал вынимать даты недели из дат, но затем у меня возникает проблема при сравнении дат разных лет.

Это можно обойти?


person starbyone    schedule 29.08.2018    source источник


Ответы (3)


Итак, после некоторого чтения, нет собственного способа сделать это. Но вот обходной путь:

DECLARE @A DATE = '20180829' -- August 29th
DECLARE @B DATE = '20180902' -- September 2nd

--We need to back each date up to the first day of its week.
DECLARE @A_FIRSTWEEKDAY DATE = DATEADD(DAY, -(DATEPART(WEEKDAY, @A) - 1), @A)
DECLARE @B_FIRSTWEEKDAY DATE = DATEADD(DAY, -(DATEPART(WEEKDAY, @B) - 1), @B)

/*The WEEKDAY part counts Sunday as day 1. If the original date was
a Sunday, it backed up zero days and it still needs to back up six
days. If it was any other day, it backed all the way up to Sunday
and now it needs to move forward one day.*/
IF DATEPART(WEEKDAY, @A) = 1
     BEGIN SET @A_FIRSTWEEKDAY = DATEADD(DAY, -6, @A_FIRSTWEEKDAY) END
ELSE BEGIN SET @A_FIRSTWEEKDAY = DATEADD(DAY,  1, @A_FIRSTWEEKDAY) END
IF DATEPART(WEEKDAY, @B) = 1 
     BEGIN SET @B_FIRSTWEEKDAY = DATEADD(DAY, -6, @B_FIRSTWEEKDAY) END
ELSE BEGIN SET @B_FIRSTWEEKDAY = DATEADD(DAY,  1, @B_FIRSTWEEKDAY) END

--Now we can just difference the weeks.
SELECT DATEDIFF(DAY, @A_FIRSTWEEKDAY, @B_FIRSTWEEKDAY) / 7
person Adam C    schedule 29.08.2018
comment
Это приводит к тому, что я получаю только разницу в неделю, а не совокупное количество недель с 2005 года: SET @A = '20050129'; НАБОР @B = '20180902'; Результат: 31, хотя их разница в годах. - person starbyone; 30.08.2018
comment
Ты прав. Я обновился другим решением, рассчитанным на разные годы. - person Adam C; 31.08.2018
comment
Да, хотя вам нужно добавить недостающую скобку к вашим переменным FIRSTWEEKDAY. Ваш метод более гибкий / правильный / быстрый, чем метод ниже? - person starbyone; 03.09.2018
comment
@starbyone, недостающие скобки исправил. Опубликованный вами метод одинаково точен. Вам решать, что вам больше нравится. Мой очень многословен ... Я бы предпочел тот, который вы нашли, если бы я сам не придумал. :) - person Adam C; 06.09.2018

Это связано с тем, что DATEDIFF всегда использует воскресенье в качестве первого дня недели, чтобы функция работала детерминированным образом: https://docs.microsoft.com/en-us/sql/t-sql/functions/dateiff-transact-sql?view=sql-server-2017#comments

Итак, 20180902 (воскресенье) - первый день следующей недели.

person Pm Duda    schedule 29.08.2018

SELECT DATEDIFF(ww, DATEADD(dd,-1, @A ), DATEADD(dd,-1,@B)) 
--Seems to do the trick?

Взято из: Количество недель и неполных недель между два дня рассчитаны неправильно

Хотя я не понимаю, почему другой пост в ссылке добавляет 1 в конце.

person starbyone    schedule 29.08.2018
comment
Для чего нужен актерский состав? - person shawnt00; 29.08.2018
comment
Я думаю, что -1 будет меняться из года в год. Идея состоит в том, чтобы переводить даты на соответствующее количество дней, чтобы работала логика воскресенья datediff. - person shawnt00; 29.08.2018
comment
@ shawnt00: Приведение связано с тем, что некоторая логика использует даты в качестве первичных ключей (как целые числа), не связанных с проблемой - я отредактирую это. - person starbyone; 30.08.2018