Я не знаю, почему вы приняли ответ Эстебана, учитывая, что ваш ожидаемый результат таков. Только 6 рядов.
PersonID Hdate
10 2019/02/01
11 2019/02/01
12 2019/02/01
10 2019/02/05
11 2019/02/05
10 2019/02/06
И все же запрос Эстебана выдает 7 строк. В праздник 6 февраля неправильно включается лицо № 11, которому разрешено иметь выходной 6 февраля. Это противоречит определению вашей проблемы:
In date (2019/02/06) AllBranch is 0 so:
* ...
* PersonID-11 work in 2 branch(2,3) and only branch 3 is NOT define closed
in BranchHoliday table so is in NOT holiday
Предположительно, выходные лица человека должны быть проверены (объединены) по таблице праздничных дней, верно? Но запрос Эстебана не делает этого.
Запрос Эстебана дает неправильный вывод:
Тест в реальном времени: http://sqlfiddle.com/#!18/86728/2
| PersonID | Date |
|----------|------------|
| 10 | 2019-02-01 |
| 11 | 2019-02-01 |
| 12 | 2019-02-01 |
| 10 | 2019-02-05 |
| 11 | 2019-02-05 |
| 10 | 2019-02-06 |
| 11 | 2019-02-06 |
И учитывая эти разные данные:
Праздник
ID Date AllBranch
1 2019/02/01 1
2 2019/02/05 0
3 2019/02/06 0
4 2019/04/02 0
BranchHoliday
ID HolidayID BranchID
1 2 2
2 2 3
3 3 2
4 4 2
5 4 4
Запрос Эстебана снова дает неправильный вывод:
Тест в реальном времени: http://sqlfiddle.com/#!18/10348/1
| PersonID | Date |
|----------|------------|
| 10 | 2019-02-01 |
| 11 | 2019-02-01 |
| 12 | 2019-02-01 |
| 10 | 2019-02-05 |
| 11 | 2019-02-05 |
| 12 | 2019-02-05 |
| 10 | 2019-02-06 |
| 11 | 2019-02-06 |
| 12 | 2019-02-06 |
| 10 | 2019-04-02 |
| 11 | 2019-04-02 |
| 12 | 2019-04-02 |
Это должно привести к этому:
Тест в реальном времени: http://sqlfiddle.com/#!17/7b6be/1
| id | date |
|----|------------|
| 10 | 2019-02-01 |
| 11 | 2019-02-01 |
| 12 | 2019-02-01 |
| 10 | 2019-02-05 |
| 11 | 2019-02-05 |
| 10 | 2019-02-06 |
| 10 | 2019-04-02 |
| 12 | 2019-04-02 |
И учитывая эти данные. Обратите внимание, что только 2 человека в филиале № 5 могут иметь выходной 2 апреля.
Праздник
ID Date AllBranch
1 2019/02/01 1
2 2019/02/05 0
3 2019/02/06 0
4 2019/04/02 0
BranchHoliday
ID HolidayID BranchID
1 2 2
2 2 3
3 3 2
4 4 5
Запрос Эстебана снова приводит к неправильным выводам, поскольку только 2 человека из филиала № 5 могут иметь выходной 2 апреля. Тем не менее, его запрос включает лиц, которые не должны иметь выходных 2 апреля. № 11 не включены в ветку № 5, их не должно быть 2 апреля.
Тест в реальном времени: http://sqlfiddle.com/#!18/fd1d3/1
| PersonID | Date |
|----------|------------|
| 10 | 2019-02-01 |
| 11 | 2019-02-01 |
| 12 | 2019-02-01 |
| 10 | 2019-02-05 |
| 11 | 2019-02-05 |
| 10 | 2019-02-06 |
| 11 | 2019-02-06 |
| 10 | 2019-04-02 |
| 11 | 2019-04-02 |
Это должно произвести это. Ни одному сотруднику не разрешается иметь выходной 2 апреля, даже человеку № 10 не разрешается иметь выходной 2 апреля, так как человек № 10 находится только в филиале № 2. Только люди в филиале № 5 могут иметь выходной.
Живой тест: http://sqlfiddle.com/#!17/299f73/1
| id | date |
|----|------------|
| 10 | 2019-02-01 |
| 11 | 2019-02-01 |
| 12 | 2019-02-01 |
| 10 | 2019-02-05 |
| 11 | 2019-02-05 |
| 10 | 2019-02-06 |
Это правильный запрос (версия Postgres):
Тест в реальном времени: http://sqlfiddle.com/#!17/6cf97/2
select h.date, p.id
from holiday h
cross join person p
join personbranch pb
on p.id = pb.personid
left join branchholiday bh
on h.id = bh.holidayid and pb.branchid = bh.branchid
group by h.date, p.id
having
every(h.allbranch)
or
-- choose only every person whose branch ids are all present in branchholiday
-- filtered by holidayid from holiday.id
every(bh.branchid is not null)
order by h.date, p.id
Вывод соответствует ожидаемому выводу определения вашей проблемы:
| id | date |
|----|------------|
| 10 | 2019-02-01 |
| 11 | 2019-02-01 |
| 12 | 2019-02-01 |
| 10 | 2019-02-05 |
| 11 | 2019-02-05 |
| 10 | 2019-02-06 |
Версия SQL Server:
Тест в реальном времени: http://sqlfiddle.com/#!18/41a54/3
select p.id, h.date
from holiday h
cross join person p
join personbranch pb
on p.id = pb.personid
left join branchholiday bh
on h.id = bh.holidayid and pb.branchid = bh.branchid
group by h.date, p.id
having
count(case when h.allbranch = 1 then 1 end) = count(*)
or
-- choose only every person whose branch ids are all present in branchholiday
-- filtered by holidayid from holiday.id
count(case when bh.branchid is not null then 1 end) = count(*)
order by h.date, p.id
Вывод соответствует ожидаемому результату определения вашей проблемы:
| id | date |
|----|------------|
| 10 | 2019-02-01 |
| 11 | 2019-02-01 |
| 12 | 2019-02-01 |
| 10 | 2019-02-05 |
| 11 | 2019-02-05 |
| 10 | 2019-02-06 |
Это идиома другого SQL Server every
. Вы можете изменить подход count(condition) = count(*)
на min
:
Тест в реальном времени: http://sqlfiddle.com/#!18/41a54/4
having
min(case when h.allbranch = 1 then 1 else 0 end) = 1
or
-- choose only every person whose branch ids are all present in branchholiday
-- filtered by holidayid from holiday.id
min(case when bh.branchid is not null then 1 else 0 end) = 1
Вывод соответствует ожидаемому результату определения вашей проблемы:
| id | date |
|----|------------|
| 10 | 2019-02-01 |
| 11 | 2019-02-01 |
| 12 | 2019-02-01 |
| 10 | 2019-02-05 |
| 11 | 2019-02-05 |
| 10 | 2019-02-06 |