У меня есть база данных о старых автомобилях, их владельцах, событиях и участниках тех событий как таковых:
Изображение используемых таблиц:
ПК: первичный ключ 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
Я также пытался использовать объединения и группировать, чтобы получить правильный результат, но ничего не получаю. Кто-нибудь знает, как мне нужно сформировать подзапрос, чтобы я мог получить необходимые результаты?
Пожалуйста, добавьте образец и ожидаемые данные.
Присоединиться/группировать по будет работать нормально. Присоединитесь ко всем своим таблицам, а затем подсчитайте отдельные идентификаторы событий при группировке по идентификатору участника. В чем заключалась проблема, связанная с подходом объединения?
Кажется странным дизайн, когда автомобиль может присутствовать на мероприятии, а не участник, и что, если 2 участника имеют доли в одной машине?
@Charleh join/group by сделал свое дело. Когда я исполнял это, я, должно быть, забыл о том, что я думаю, но это было раньше.
@P.Salmon Я должен был уточнить, что эти мероприятия похожи на автомобильные выставки очень старых и ценных автомобилей. Вот почему у одного человека может быть более 1 машины.
Не уверен, что вы используете это точное утверждение, но ваш синтаксис имеет несколько проблем. Вы используете несуществующие псевдонимы (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, я перевел это с голландского и, должно быть, пропустил это. Является ли группа обязательной для получения таких результатов?
Группировать по обязательно для агрегирования, предполагая, что вы не просто используете агрегированный столбец сам по себе (если вам нужно только агрегированное значение и никакие другие столбцы, вам не нужно группировать в SQL Server, так как предполагается, что вы просто хотели агрегировать по всему набору и вернуть 1 результат)
Итак, вам нужны разные события, которые посещал участник. У участника есть автомобили, которые посещают мероприятия. Поскольку разные автомобили могут участвовать в одних и тех же событиях, вам нужно выделить из событий:
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
Большое спасибо, ваш код работает отлично, я должен был придерживаться группы, а не пробовать подзапросы.
Вам всегда нужно использовать GROUP BY
, когда вы смешиваете обычные столбцы с агрегатными функциями. Ничего общего с подзапросами. В вашем запросе у вас есть m.memberId
как обычный столбец и count(a.eventId)
как агрегатная функция. Это будет означать, что вам придется использовать group by m.memberId
(игнорируя другие ошибки в вашем запросе).
Обычно у вас нет коррелированных подзапросов при выполнении
IN
. (Но когда вы делаетеEXISTS
, у вас есть коррелированные подзапросы.)