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

#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 = ?
)