Получить количество строк для каждой объединенной таблицы для каждой строки в основной таблице

У меня есть три таблицы в моей базе данных. Центральная таблица в звездообразной схеме — посылки со столбцом PK, называемым id. Каждая отправляющая запись может иметь ноль или более строк в таблицах открывается.

sendings.id = opens.sending_id

Точно так же третья таблица, называемая clicks, имеет следующую связь с таблицей отправки (одна отправка может иметь ноль или более кликов):

sendings.id = clicks.sending_id

Обе таблицы открывается и клики имеют свой уникальный столбец идентификатора, который называется id. То, что я хотел бы иметь в одном запросе, это количество всех связанных открытий и кликов для каждой отправки. Следующий запрос, похоже, не соответствует этому требованию.

select s.id,
    count(o.id) as open_count,
    count(c.id) as click_count
from sendings s
left join opens o on s.sending_id = o.sending_id
left join clicks c on s.sending_id = c.sending_id
group by s.id;
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
0
12
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Простое решение — использовать count(distinct):

select s.id,
       count(distinct o.id) as open_count,
       count(distinct c.id) as click_count
from sendings s left join
     opens o
     on s.sending_id = o.sending_id left join
     clicks c
     on s.sending_id = c.sending_id
group by s.id;

count() просто подсчитывает количество не-NULL значений.

В общем, более производительное решение — это коррелированные подзапросы или агрегация перед join:

select s.id, o.open_count, c.click_count
from sendings s left join
     (select o.sending_id, count(*) as open_count
      from opens o
      group by o.sending_id
     ) o
     on s.sending_id = o.sending_id left join
     (select c.sending_id, count(*) as click_count
      from clicks c
      group by c.sending_id
     ) c
     on s.sending_id = c.sending_id;

Обратите внимание, что внешний group by в этом случае не обязателен.

О, спасибо тебе большое. Какое из двух решений вы бы выбрали? Сначала я не ошибся, но distinct отсутствовал, и мне было интересно, почему я получаю одинаковые числа.

disasterkid 29.05.2019 16:09

@disasterkid . . . Если ваши подсчеты больше, чем вы можете сосчитать на руках, используйте второе решение.

Gordon Linoff 29.05.2019 16:10

Другие вопросы по теме