Было бы проще, если бы вы могли добавить столбец для хранения даты начала недели в вашей календарной таблице (таблица timecard
).Тогда мы могли бы просто агрегировать все выборки, представленные в течение каждого интервала.
Учитывая текущую структуру базы данных, одним из решений было бы эмулировать это поведение, используя коррелированный подзапрос.Далее условие NOT EXISTS
гарантирует, что мы объединяем текущую запись sample
с соответствующей записью timecard
.Внешний запрос выполняет агрегирование по имени и интервалу дат, а предложение HAVING BY
фильтрует записи, в которых не было достигнуто минимальное количество рабочих часов.
SELECT
s.name,
s.WeekEnding DateEntered,
t.WeekEnding,
t.MinimumHours,
SUM(s.HoursWorked) TotalHoursWorked
FROM sample s
INNER JOIN timecard t
ON s.WeekEnding <= t.WeekEnding
AND NOT EXISTS (
SELECT 1
FROM timecard t1
WHERE s.WeekEnding <= t.WeekEnding AND t1.WeekEnding > t.WeekEnding
)
GROUP BY
s.name,
s.WeekEnding,
t.WeekStart,
t.WeekEnding,
t.MinimumHours
HAVING SUM(s.HoursWorked) < t.MinimumHours
Начиная с SQLServer 2017, оконные функциисделать это проще.Мы можем получить доступ к предыдущей записи, используя LAG()
:
SELECT
s.name,
s.WeekEnding DateEntered,
t.WeekStart,
t.WeekEnding,
t.MinimumHours,
SUM(s.HoursWorked) TotalHoursWorked
FROM
sample s
INNER JOIN (
SELECT
WeekEnding,
MinimumHours,
LAG(WeekEnding) OVER(ORDER BY WeekEnding) WeekStart
FROM timecard
) t
ON s.WeekEnding > t.WeekStart AND s.WeekEnding <= t.WeekEnding
GROUP BY
s.name,
s.WeekEnding,
t.WeekStart,
t.WeekEnding,
t.MinimumHours