Как правильно объединить эти серии, чтобы этот запрос возвращал результаты, в которых count = 0 в Postgresql SQL? - PullRequest
1 голос
/ 25 мая 2020

У меня есть следующий запрос, который выполняется в базе данных Postgresql:

SELECT NULL AS fromdate,
       l.eventlevel,
       SUM(CASE
               WHEN e.id IS NULL THEN 0
               ELSE 1
           END) AS COUNT
FROM event e
RIGHT JOIN
  (SELECT generate_series(0, 3) AS eventlevel) l ON e.event_level = l.eventlevel
WHERE e.project_id = :projectId
GROUP BY l.eventlevel
ORDER BY l.eventlevel DESC

С (обрезанной) таблицей событий:

TABLE public.event
    id uuid NOT NULL,
    event_level integer NOT NULL

Это вариант для разделенной запрос, но со всеми данными, отсюда NULL fromdate. Я пытаюсь получить подсчеты из таблицы event и подсчитать для каждого уровня события. Но я также хочу, чтобы число 0 возвращалось, когда нет никаких событий для этого конкретного event_level. Но текущее правое соединение не выполняет эту работу. Что я делаю не так? Я также попытался добавить OR e.project_id IS null, думая, что он может отфильтровывать 0 счетчиков. Или это будет работать с CROSS JOIN, и если да, то как?

Текущий результат:

+----------+------------+-------+
| fromdate | eventlevel | count |
+----------+------------+-------+
| null     |          3 |     1 |
+----------+------------+-------+

Желаемый результат:

+----------+------------+-------+
| fromdate | eventlevel | count |
+----------+------------+-------+
| null     |          3 |     1 |
| null     |          2 |     0 |
| null     |          1 |     0 |
| null     |          0 |     0 |
+----------+------------+-------+

Ответы [ 2 ]

1 голос
/ 25 мая 2020

Я рекомендую избегать RIGHT JOIN s и использовать LEFT JOIN s. Они просто проще следовать логике c - сохранить все в первой таблице и сопоставить строки в последующих.

Ваша проблема заключается в размещении фильтра - он отфильтровывает внешние соединенные строки . Так что необходимо добавить go в предложение ON. Я бы порекомендовал:

SELECT NULL AS fromdate, gs.eventlevel,
       COUNT(e.id) as count
FROM generate_series(0, 3) gs(eventlevel) LEFT JOIN
     event e
     ON e.event_level = gs.eventlevel AND e.project_id = :projectId
GROUP BY gs.eventlevel
ORDER BY gs.eventlevel DESC;

Обратите внимание на другие упрощения:

  • Для generate_series не требуется подзапрос.
  • Вы можете использовать COUNT() вместо Ваш case logi c.
1 голос
/ 25 мая 2020

Вы должны переместить условие e.project_id из предложения WHERE в предложение ON, чтобы получить истинный RIGHT JOIN результат:

           ...
           END) AS COUNT
FROM event e
RIGHT JOIN
  (SELECT generate_series(0, 3) AS eventlevel) l ON e.event_level = l.eventlevel
AND e.project_id = :projectId
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...