Вот что я придумал благодаря 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