Как присоединиться к календарной таблице, чтобы получить значения NULL, если в основной таблице нет значений? - PullRequest
0 голосов
/ 26 марта 2020

Представьте, что у меня есть таблица за февраль с пользователями и их нарушениями изоляции карантина COVID-19 в течение одного дня. Если пользователь не нарушал изоляцию в течение всего дня, такой строки в таблице на эту дату нет.

user date       violations
1    2020-02-01 2
1    2020-02-03 1
1    2020-02-15 2
3    2020-02-04 1
3    2020-02-24 3

Какой тип объединения следует использовать для моего запроса, чтобы каждый день в феврале отображался для для каждого пользователя и значения столбца нарушений (ноль или 0, если такой строки нет):

user date       violations
1    2020-02-01 2
1    2020-02-02 NULL
1    2020-02-03 1
1    2020-02-04 NULL
...
1    2020-02-29 NULL
3    2020-02-01 NULL
3    2020-02-02 NULL
3    2020-02-03 NULL
3    2020-02-04 1
...
3    2020-02-29 NULL

У меня есть таблица календаря на февраль:

date
2020-02-01
2020-02-02
...
2020-02-29

Я пробовал полное внешнее объединение , но это работает, как я ожидал, только для одного пользователя.

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Если у вас есть отдельная таблица пользователей, вам нужно перекрестное объединение календаря и пользователей, а затем оставить внешнее объединение с таблицей нарушений, как уже показал Гордон Линофф.

Однако, если вы не имеет таблицу пользователей, и вы должны просто выбрать их из таблицы нарушений, тогда вам следует использовать внешнее соединение раздела , которое существует именно для этой цели:

select v.user, c.date, v.violations
from   calendar c left outer join violations v
       PARTITION BY (v.user)                      -- this is what you must add
       on c.date = v.date
order  by user,date
;

Преимущество заключается в том, что вам не нужно читать таблицу нарушений дважды.

Обратите внимание, что DATE и USER и ключевые слова не должны использоваться в качестве имен столбцов; Я последовал твоему примеру, но твое руководство нехорошо.

1 голос
/ 26 марта 2020

Используйте cross join для генерации строк и затем left join для ввода существующих данных:

select c.date, u.user, v.violations
from calendar c cross join
     (select distinct user from violations) u left join
     violations v
     on c.date = v.date and u.user = v.user

Если у вас есть отдельная таблица для пользователей, используйте ее вместо подзапроса для u. В конце концов, возможно, есть пользователи, которые не имели нарушений в феврале.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...