SQL запрос хотя бы один из чего-то
У меня есть куча пользователей, каждый из которых имеет много постов. Схема:
Users: id
Posts: user_id, rating
Как найти всех пользователей, у которых есть хотя бы один пост с рейтингом выше, скажем, 10?
Я не уверен, если я должен использовать подзапрос для этого, или если есть более простой способ.
спасибо!
6 ответов
чтобы найти всех пользователей хотя бы с одним постом с рейтингом выше 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.
корреляция (где p.user_id = u.id), поэтому это называется коррелированным подзапросом и возвращает только строки от пользователей таблица, где значения id совпадают, в дополнение к сравнению рейтинга.
EXISTS также быстрее, в зависимости от ситуации, потому что он возвращает true, как только критерии выполнены - дубликаты не имеют значения.
вы можете присоединиться к таблицам, чтобы найти соответствующих пользователей, и использовать разные, так что каждый пользователь находится в результирующем наборе не более одного раза, даже если у них есть несколько сообщений с рейтингом > 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 * from users INNER JOIN posts p on users.id = p.user_id where p.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;
кроме того, это скажет вам, что их самый высокий рейтинг.
правильным ответом на ваш вопрос, как указано, является ответ OMG Ponies, где существует более описательный и почти всегда быстрее. Но "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.