У меня есть набор Пользователей, у каждого из которых есть много Сообщений. Схема:
Users: id
Posts: user_id, rating
Как я нахожу всех Пользователей, у которых есть по крайней мере одно сообщение с оценкой выше, скажем, 10?
Я не уверен, должен ли я использовать подзапрос для этого, или если существует более легкий путь.
Спасибо!
Чтобы найти всех пользователей, у которых есть хотя бы одно сообщение с рейтингом выше 10, используйте:
SELECT u.*
FROM USERS u
WHERE EXISTS(SELECT NULL
FROM POSTS p
WHERE p.user_id = u.id
AND p.rating > 10)
EXISTS не заботится об операторе SELECT. внутри него - вы можете заменить NULL на 1/0, что должно привести к математической ошибке при делении на ноль ... Но этого не произойдет, потому что EXISTS касается только фильтрации в предложении WHERE.
Корреляция (WHERE p.user_id = u.id) - это то, почему это называется коррелированным подзапросом и будет возвращать только те строки из таблицы USERS, где значения id совпадают, в дополнение к сравнению рейтингов.
EXISTS также быстрее, в зависимости от ситуации, потому что он возвращает истину, как только критерии соблюдены - дубликаты не имеют значения.
Правильным ответом на ваш вопрос, как указано, является ответ OMG Ponies, WHERE EXISTS более описателен и почти всегда быстрее. Но "SELECT NULL" выглядит очень уродливо и нелогично, на мой взгляд. Я видел SELECT * или SELECT 1 в качестве лучшей практики для этого.
Другой способ, на случай, если мы собираем ответы:
SELECT u.id
FROM users u
JOIN posts p on u.id = p.user_id
WHERE p.rating > 10
GROUP BY u.id
HAVING COUNT(*) > 1
Это может быть полезно, если вы тестируете не всегда 1.
Используйте внутреннее соединение:
SELECT * from users INNER JOIN posts p on users.id = p.user_id where p.rating > 10;
Вы можете присоединиться к таблицам, чтобы найти соответствующих пользователей, и использовать DISTINCT, чтобы каждый пользователь попадал в результирующий набор не более одного раза, даже если у них есть несколько сообщений с рейтингом> 10:
select distinct u.id,u.username
from users u inner join posts p on u.id = p.user_id
where p.rating > 10
select distinct id
from users, posts
where id = user_id and rating > 10
SELECT max(p.rating), u.id
from users u
INNER JOIN posts p on users.id = p.user_id
where p.rating > 10
group by u.id;
Кроме того, здесь вы узнаете, какой у них самый высокий рейтинг.