Борьба с коррелированными подзапросами в SQL

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

Изображение используемых таблиц:

Борьба с коррелированными подзапросами в SQL

ПК: первичный ключ FK: внешний ключ

Теперь мне нужно получить количество различных событий (eventId), которые посетил каждый участник (memberId). Важное примечание: участник может иметь несколько автомобилей, каждый из которых может посещать мероприятия.

Вот одна из моих попыток:

select m.memberId, count(a.eventId).
from members m where m.memberId in (select c.memberId from cars c where m.memberId =
    c.memberId and c.carId in
    (select d.carId from attendants a where c.carId = d.carId))
order by m.memberId

Я также пытался использовать объединения и группировать, чтобы получить правильный результат, но ничего не получаю. Кто-нибудь знает, как мне нужно сформировать подзапрос, чтобы я мог получить необходимые результаты?

Обычно у вас нет коррелированных подзапросов при выполнении IN. (Но когда вы делаете EXISTS, у вас есть коррелированные подзапросы.)

jarlh 28.05.2019 11:59

Пожалуйста, добавьте образец и ожидаемые данные.

mkRabbani 28.05.2019 11:59

Присоединиться/группировать по будет работать нормально. Присоединитесь ко всем своим таблицам, а затем подсчитайте отдельные идентификаторы событий при группировке по идентификатору участника. В чем заключалась проблема, связанная с подходом объединения?

Charleh 28.05.2019 12:01

Кажется странным дизайн, когда автомобиль может присутствовать на мероприятии, а не участник, и что, если 2 участника имеют доли в одной машине?

P.Salmon 28.05.2019 12:03

@Charleh join/group by сделал свое дело. Когда я исполнял это, я, должно быть, забыл о том, что я думаю, но это было раньше.

kyllion001 28.05.2019 12:30

@P.Salmon Я должен был уточнить, что эти мероприятия похожи на автомобильные выставки очень старых и ценных автомобилей. Вот почему у одного человека может быть более 1 машины.

kyllion001 28.05.2019 12:32
Освоение архитектуры микросервисов с 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
6
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Не уверен, что вы используете это точное утверждение, но ваш синтаксис имеет несколько проблем. Вы используете несуществующие псевдонимы (d.CarID — какая таблица d?), и у вас нет оператора group by в конце, который сообщает движку, из каких столбцов вы хотите сохранить значения. Попробуйте что-то вроде этого:

select member_ID,
  count(*)
from (
  select distinct a.eventID, m.memberID
  from attendants a
  inner join cars c
  on a.carID = c.car_ID
  inner join members m
  on c.memberID = m.memberID
  group by a.eventID, m.memberID
)
group by memberID

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

Вы правы насчет d.CarId, я перевел это с голландского и, должно быть, пропустил это. Является ли группа обязательной для получения таких результатов?

kyllion001 28.05.2019 12:15

Группировать по обязательно для агрегирования, предполагая, что вы не просто используете агрегированный столбец сам по себе (если вам нужно только агрегированное значение и никакие другие столбцы, вам не нужно группировать в SQL Server, так как предполагается, что вы просто хотели агрегировать по всему набору и вернуть 1 результат)

Charleh 28.05.2019 14:19
Ответ принят как подходящий

Итак, вам нужны разные события, которые посещал участник. У участника есть автомобили, которые посещают мероприятия. Поскольку разные автомобили могут участвовать в одних и тех же событиях, вам нужно выделить из событий:

select m.memberId, count(distinct a.eventId)
from members m 
  join cars c on c.memberId = m.memberId
  join attendants a on a.carId = c.carId
group by m.memberId

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

kyllion001 28.05.2019 12:27

Вам всегда нужно использовать GROUP BY, когда вы смешиваете обычные столбцы с агрегатными функциями. Ничего общего с подзапросами. В вашем запросе у вас есть m.memberId как обычный столбец и count(a.eventId) как агрегатная функция. Это будет означать, что вам придется использовать group by m.memberId (игнорируя другие ошибки в вашем запросе).

slaakso 28.05.2019 12:30

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