Суммирование с использованием левого соединения

Вопрос или проблема

Я хотел бы посчитать доступные waves (LEFT OUT JOIN). Моя проблема в том, что у меня также есть другой LEFT OUTER JOIN на invitations.

У мероприятия много волн. У мероприятия много приглашений.

Я протестировал 2 варианта.

Вариант 1

SELECT CAST(sum((case when (waves.id IS NOT NULL) then 1 else 0 end)) AS INTEGER) as total_waves
FROM "events"
         LEFT OUTER JOIN "waves" ON "waves"."wavable_type" = 'Event' AND
                                               "waves"."wavable_id" = "events"."id"
         LEFT OUTER JOIN "invitations" ON "invitations"."event_id" = "events"."id"
WHERE "events"."uuid" = 'XXX'
GROUP BY "events"."id"

-> Это дает мне количество созданных приглашений, если оно больше количества волн.

Вариант 2 (с DISTINCT)

SELECT CAST(sum(DISTINCT(case when (waves.id IS NOT NULL) then 1 else 0 end)) AS INTEGER) as total_waves
FROM "events"
         LEFT OUTER JOIN "waves" ON "waves"."wavable_type" = 'Event' AND
                                               "waves"."wavable_id" = "events"."id"
         LEFT OUTER JOIN "invitations" ON "invitations"."event_id" = "events"."id"
WHERE "events"."uuid" = 'XXX'
GROUP BY "events"."id"

-> Всегда возвращает мне 1, что, я предполагаю, является количеством мероприятий, соответствующих запросу (я определил его по uuid).

Ответ или решение

Для решения вашей задачи с подсчетом количества волн, доступных для конкретного события, при этом используя LEFT JOIN, необходимо учитывать, что ваши запросы могут давать некорректные результаты в связи с тем, что вы подводите результаты по количеству записей о приглашениях, а не по количеству волн.

Проблема:
Ваши два варианта запросов возвращают неправильное количество волн, так как при использовании LEFT JOIN с invitations происходит дублирование строк, что влияет на вычисление суммы.

Решение:
Вместо использования SUM в сочетании с CASE, лучше использовать COUNT для того, чтобы посчитать общее количество волн, при этом применяя DISTINCT для предотвращения дублирования. Для правильного подсчета вам нужно применить COUNT(DISTINCT waves.id), чтобы избежать подсчета одних и тех же волн несколько раз из-за связанных приглашений.

Вот как может выглядеть исправленный запрос:

SELECT 
    COUNT(DISTINCT waves.id) AS total_waves
FROM 
    "events"
LEFT OUTER JOIN 
    "waves" ON "waves"."wavable_type" = 'Event' AND "waves"."wavable_id" = "events"."id"
LEFT OUTER JOIN 
    "invitations" ON "invitations"."event_id" = "events"."id"
WHERE 
    "events"."uuid" = 'XXX'
GROUP BY 
    "events"."id"

Объяснение:

  1. Мы используем COUNT(DISTINCT waves.id) для того, чтобы получить количество уникальных волн, связанных с данным событием.
  2. LEFT JOIN на таблице invitations не влияет на количество волн, так как мы управляем этим через DISTINCT.
  3. Условия в WHERE и GROUP BY помогают изолировать события по UUID, что позволяет получить верные результаты для конкретного события.

Таким образом, данный запрос позволит вам получить точное количество волн, доступных для мероприятия, без влияния связанных приглашений.

Оцените материал
Добавить комментарий

Капча загружается...