Найти следующее вхождение дня недели в SQL - PullRequest
0 голосов
/ 26 января 2012

Я пытаюсь обновить предложение WHERE sproc отчета SQL, чтобы проверить, попадает ли данная дата или до следующего вхождения класса. Классы имеют StartDate и происходят один раз в неделю в один и тот же день каждую неделю. Учитывая StartDate, как я могу найти следующее вхождение этого дня недели?

например. Если StartDate - 18.01.2012, среда, и я запускаю отчет по состоянию на сегодня, 26.01.2012, мне нужно найти 1.02.2012, следующую за средой после 1/26. Если начальная дата 1/19, четверг, и я запускаю отчет сегодня, формула должна дать мне четверг 1/26, что сегодня.

Вот такая идея в SQL:

SELECT *
FROM tbl_Class cs
INNER JOIN tbl_Enrollment sce ON cs.pk_ClassID = sce.fk_ClassID
WHERE ...
AND sce.StartDate < [Find date of next class after @AsOfDate using cs.StartDate]

Ответы [ 3 ]

1 голос
/ 26 января 2012

Вот пример SQL, который я придумал. 3 итерации, чтобы вы могли следить, как я дошел до конца. Третья итерация должна быть чем-то, что вы можете включить в предложение WHERE, подставив имена столбцов для переменных.

Установка:

DECLARE @Startdate DATETIME,@currentdate datetime
SET @Startdate = '1-26-2012' 
SET @Currentdate = '1-23-2012'

--This section just normalizes it so you can use 7 as the interval
--The offset depends on your current setting for DATEFIRST, U.S. English default is 7, Sunday.
-- see http://msdn.microsoft.com/en-us/library/ms187766.aspx 
DECLARE @StartDateWorkingDayOfWeek int,@CurrentDateWorkingDayOfWeek int
SELECT @StartDateWorkingDayOfWeek =(DATEPART(weekday,@Startdate)-2)
SELECT @CurrentDateWorkingDayOfWeek=(DATEPART(weekday,@Currentdate)-2)

Итерация # 1

--Iteration 1 
IF @StartDateWorkingDayOfWeek < @CurrentDateWorkingDayOfWeek
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 + 7,@StartDateWorkingDayOfWeek)
else
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 + 0,@StartDateWorkingDayOfWeek)

Итерация # 2

--Iteration 2
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 + 

CASE WHEN @StartDateWorkingDayOfWeek < @CurrentDateWorkingDayOfWeek
    then 7
    ELSE 0
    end

    ,@StartDateWorkingDayOfWeek)

Итерация # 3

--iteration 3
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 + 

CASE WHEN (DATEPART(weekday,@Startdate)-2) < (DATEPART(weekday,@Currentdate)-2)
    then 7
    ELSE 0
    end

    ,(DATEPART(weekday,@Startdate)-2))

Шляпа подсказка к этой статье: http://www.sqlmag.com/article/tsql3/datetime-calculations-part-3

0 голосов
/ 25 марта 2015

Я получил ответ с помощью простого описания случая.
В вашей ситуации @targetDOW будет днем ​​недели в классе.

0 голосов
/ 26 января 2012

Вот что я придумал благодаря TetonSig и его ссылке на эту ссылку: http://www.sqlmag.com/article/tsql3/datetime-calculations-part-3

Мы можем получить дату предыдущего понедельника без учета текущей даты (@AsOfDate) следующим образом:

SELECT DATEADD(day, DATEDIFF(day,0, @AsOfDate-1) /7*7, 0);

Получает количество дней между 01.01.1900 и @AsOfDate в днях. / 7 * 7 преобразует это в целые недели, а затем добавляет обратно к 1/1/1900 (понедельник), чтобы получить понедельник до @AsOfDate. -1 делает его исключающим @AsOfDate. Без минуса 1, если бы @AsOfDate был в понедельник, он был бы засчитан как «предыдущий» понедельник.

Далее автор показывает, что для получения включительного значения в следующий понедельник нам просто нужно добавить 7 к исключительной формуле предыдущего понедельника:

SELECT DATEADD(d, DATEDIFF(day,0, @AsOfDate-1) /7*7, 0)+7;

Вуаля! Теперь у нас первый понедельник или после @AsOfDate. Единственная проблема в том, что понедельник (0) выше - это движущаяся цель в моем случае. Мне нужен первый [DayOfWeek], определенный по дате урока, а не первый понедельник. Мне нужно поменять расчет ClassDayOfWeek на 0 выше:

DATEADD(d, DATEDIFF(d, [ClassDayOfWeek], @AsOfDate-1)/7*7, [ClassDayOfWeek])+7

Я хотел рассчитать ClassDayOfWeek, не будучи зависимым или не связавшись с настройкой @@ datefirst. Поэтому я рассчитал это относительно базовой даты:

DATEDIFF(d, 0, StartDate)%7

Это дает 0 для Mon, 6 для Sun, поэтому теперь мы можем подключить его для [ClassDayOfWeek]. Я должен указать, что это значение 0-6 - даты 1/1 / 1900-1 / 7/1900, представленные как int.

DATEADD(d, DATEDIFF(d, DATEDIFF(d, 0, StartDate)%7, @AsOfDate-1)/7*7, DATEDIFF(d, 0, StartDate)%7)+7

И используется по вопросу:

SELECT *
FROM tbl_Class cs
INNER JOIN tbl_Enrollment sce ON cs.pk_ClassID = sce.fk_ClassID
WHERE ...
AND sce.StartDate < DATEADD(d, 
                            DATEDIFF(d, 
                                     DATEDIFF(d, 0, cs.StartDate)%7, 
                                     @AsOfDate-1)/7*7, 
                            DATEDIFF(d, 0, cs.StartDate)%7)+7
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...