#mysql #sql #inner-join #having-clause #relational-division
#mysql #sql #внутреннее соединение #наличие-предложение #реляционное разделение
Вопрос:
Я хочу выполнить поиск всех пользователей, которые сдавали те же экзамены, что и я, в базе данных (MySQL).
Структура базы данных — это id, user_id, exam_id и дата
Ну, я сдал экзамены с идентификатором 5,8,9, я хочу знать, сколько из них сделали то же самое, что и я (например, другие пользователи, сдавшие экзамены 5,7,9, не будут учитываться, только пользователи, которые 5,8,9)
Если у кого-то экзамены 4, 5, 8 и 9, а у меня 4,8,9, это будет считаться, потому что они совпадают с тем, что мы баловались.
Не имеет значения, имеют ли другие пользователи больше
Комментарии:
1. А что, если кто-то взял 4, 5, 8 и 9?
2. разве это не может быть просто
exam_id IN (5,8,9)
? Или я что-то упускаю в вопросе?3. Это должно быть 5, 8 И 9, что даст ИЛИ
4. Если у кого-то есть экзамены 4, 5, 8 и 9, а у меня 4,8,9, это будет учитываться, потому что они совпадают с тем, что мы выполнили баловство. Не имеет значения, есть ли у других пользователей больше (извините, что я прояснил это раньше)
Ответ №1:
Вы можете использовать некоторую технику реляционного разделения:
select e.user_id
from exams e
inner join exams e1 on e1.exam_id = e.exam_id and e1.user_id <> e.user_id
where e1.user_id = ?
group by e.user_id
having count(*) = (select count(*) from exams where user_id = ?)
Это приводит к пользователям, которые сдали все экзамены, которые сдавал пользователь ?
. Если вы хотите получить точное совпадение (то есть отфильтровать пользователей, которые прошли больше тестов),:
select e.user_id
from exams e
left join exams e1
on e1.exam_id = e.exam_id
and e1.user_id <> e.user_id
and e1.user_id = ?
group by e.user_id
having count(e1.user_id) = (select count(*) from exams where user_id = ?)
Если у вас не слишком много экзаменов на пользователей, вы также можете использовать агрегацию строк:
select user_id
from exams
where user_id <> ?
group by user_id
having group_concat(exam_id order by exam_id) = (
select group_concat(exam_id order by exam_id) from exams where user_id = ?
)