#sql #sql-server #tsql #datetime #refactoring
#sql #sql-сервер #tsql #дата и время #рефакторинг
Вопрос:
Я хочу сравнить данные за текущую неделю (с 1 по 52) с данными за две недели до этого. Мне нужно убедиться, что при пересечении границы нового года сравнение продолжает работать. У меня есть рабочий предикат, например:
WHERE ( DATEPART(ww,MA.DateOpen) 1 ) % 52 = DATEPART(ww,@ImportDate) - 1
Приведенная выше логика работает, но она не учитывает ближайшие годы. Другими словами, нежелательные данные за неделю ‘X’ всех предыдущих лет будут включены в сравнение. Таким образом, предикат должен быть расширен для учета лет, что, в свою очередь, требует обработки границы нового года: неделя 1 2012 года должна сравниваться с неделей 51 2011 года.
Как это можно сделать без подробного предиката?
обновление: этот вопрос осложняется необходимостью обработки «недели года» со вторника по вторник. Моя текущая «правильная» попытка воплощена в приведенном ниже примере [VerboseCheck].
SET DATEFIRST 2
DECLARE @ImportDate date = '2011-1-4'
DECLARE @DateOpen date = '2010-12-20'
select @ImportDate,
YEAR(@DateOpen),
DATEPART(ww, @DateOpen),
YEAR(DATEADD(dd,-14,@ImportDate)),
DATEPART(ww,DATEADD(dd,-14,@ImportDate)),
CASE WHEN
YEAR(@DateOpen) DATEPART(ww, @DateOpen) =
YEAR(DATEADD(dd,-14,@ImportDate)) DATEPART(ww,DATEADD(dd,-14,@ImportDate))
THEN 1 ELSE 0 END [VerboseCheck],
CASE WHEN DATEDIFF (ww, @DateOpen, @ImportDate) =2
THEN 1 ELSE 0 END [SimpleCheck]
[SimpleCheck] был бы идеальным, но он дает другой ответ, чем [VerboseCheck]. Если я продвину @DateOpen еще на один день, то оба дают один и тот же ответ. Это говорит о том, что оба не выполняют оценку DATEFIRST одинаково.
Ответ №1:
Похоже, что здесь лучше всего использовать DateDiff. Однако, как вы отметили, DATEFIRST действительно не соблюдается.
Итак, мы просто добавляем решение Ицика Бен-Гана и получаем
WHERE DATEDIFF (ww,
DATEADD( day, -@@DATEFIRST , @DateOpen),
DATEADD( day, -@@DATEFIRST , @ImportDate)
) =2
Комментарии:
1. Я обновил свой вопрос, включив проблему DATEFIRST, которая, я думаю, не позволяет DATEDIFF работать так, как предложено.
2. Таким образом, предполагается, что tues-Mon определяет неделю, а не Sat-sun
3. На самом деле я проверил, и DateDiff уважает это нормально, но со вторника в качестве начала недели, но в 2011 году 53 недели, когда
Datefirst = 2
вы уверены, что это должно сравниваться с 51-й неделей 2011 года или нет (номер недели в 2011 — 1)4. Я снова обновил свой вопрос с помощью примера кода, показывающего, как DATEDIFF дает другой ответ.
5. Брент. Хорошее обновление. Извините, я был неправ. Я использовал неверные входные данные (рассуждения о датах могут быть болезненными). Я обновил свой ответ
Ответ №2:
почему бы и нет DATEADD('dd', -14, DateOpen)
?
Комментарии:
1. Это не совсем так. Поскольку дата на 51-й неделе 2011 года и 1-я неделя 2012 года могут отличаться друг от друга не ровно на 14 дней
Ответ №3:
Будет ли что-то вроде следующей работы для сравнения лет?
WHERE ( DATEPART(ww,MA.DateOpen) 1 ) % 52 = DATEPART(ww,@ImportDate) - 1
AND YEAR(MA.DateOpen)=YEAR(DATEADD(d, -14, @ImportDate))