таким образом, дата начала людей может быть началом отпуска, и вы можете найти конец этого отпуска, найдя дату их первой смены (минус 1 день), используя CROSS APPLY, чтобы получить ТОП 1 смены, ЗАКАЗАНОПО ДАТЕ
В необычной ситуации, когда у них нет смен, их отпуск заканчивается в день окончания их контракта.
Будущие каникулы начинаются на следующий день после смены и заканчиваются на следующий день до следующей.сдвиг (может быть найден с помощью OUTER APPLY) и по умолчанию устанавливается дата окончания контракта, если нет дальнейшего сдвига
SELECT p.name, p.contractStart vacationstart, p.ContractEnd vacationend from people p WHERE not exists(select 1 from shifts s where p.name = s.name)
UNION
SELECT p2.name,
p2.contractStart vacationstart,
dateadd(day,-1,DQ.ShiftStart) as vacationend
from PEOPLE P2
CROSS APPLY
(SELECT TOP 1 s2.ShiftStart FROM shifts s2 WHERE p2.name = s2.name order by sfiftstart) DQ
WHERE DQ.ShiftStart > p2.contractstart
UNION
select P3.NAME,
dateadd(day,1,s3.ShiftEnd) vacationstart,
COALESCE(dateadd(day,-1, DQ2.shiftStart),P3.ContractEnd) --you might have to add handling yourself for removing a case where they work on their contract end date
FROM people p3 JOIN shifts s3 on p3.name = s3.name
OUTER APPLY (SELECT TOP 1 s4.shiftStart
from shifts s4
where s4.name = p3.name
and
s4.shiftstart > s3.shiftstart
order by s4.shiftstart) DQ2
, мне трудно проверить без тестовых данных.Для сотрудника я ищу:
Начало контракта, Shift1Start - 1
Shift1End + 1, Shift2Start - 1
Shift2End + 1, Shift3Start - 1
Shift3End + 1, ContractEnd
, затем добавьте регистр без 'смещений', наконец, сдвиги могут быть смежными, что приведет к отпуску с нулевой или меньшей длительностью - вы можете отфильтровать их, сделав запрос подзапросоми просто фильтрация