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 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;

кроме того, это скажет вам, что их самый высокий рейтинг.


правильным ответом на ваш вопрос, как указано, является ответ 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.