Сравнение скользящих недель

#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))