#sql #join #subquery #relational-database #aggregate-functions
Вопрос:
Предположим, у меня есть два стола,
- Пользователь
- Публикация
Записи создаются Пользователями (т. е. в таблице записей будет внешний ключ пользователя)
Теперь мой вопрос таков,
Распечатайте сведения обо всех пользователях, у которых более 10 сообщений
Чтобы решить эту проблему, я могу ввести следующий запрос, и он даст мне желаемый результат,
SELECT * from USER where user_id in (SELECT user_id from POST group by user_id having count(user_id) > 10)
Проблема возникает, когда я также хочу распечатать количество сообщений вместе с данными пользователя. Теперь получить количество пользователей из таблицы ПОЛЬЗОВАТЕЛЕЙ невозможно. Это можно сделать только из таблицы POST. Но я не могу получить два значения из своего подзапроса, т. Е. Я не могу сделать следующее,
SELECT * from USER where user_id in (SELECT user_id, **count(user_id)** from POST group by user_id having count(user_id) > 10)
Итак, как мне решить эту проблему? Одно из решений, которое я знаю, заключается в следующем, но я думаю, что это был бы очень наивный способ решить эту проблему и сделает запрос намного сложнее, а также намного медленнее,
SELECT u.*, (SELECT po.count(user_id) from POST as po group by user_id having po.count(user_id) > 10) from USER u where u.user_id in (SELECT p.user_id from POST p group by user_id having p.count(user_id) > 10)
Есть ли какой-либо другой способ решить эту проблему с помощью подзапросов?
Комментарии:
1. Отметьте свой вопрос в базе данных, которую вы используете.
2. @GordonLinoff хорошо, я это делаю.
Ответ №1:
Переместите агрегацию в from
предложение:
SELECT u.*, p.num_posts
FROM user u JOIN
(SELECT p.user_id, COUNT(*) as num_posts
FROM post p
GROUP BY p.user_id
HAVING COUNT(*) > 10
) p
ON u.user_id = p.user_id;
Вы можете сделать это с помощью подзапросов:
select u.*
from (select u.*,
(select count(*) from post p where p.user_id = u.user_id) as num_posts
from users u
) u
where num_posts > 10;
С включенным индексом post(user_id)
это может на самом деле иметь лучшую производительность , чем версия, использующая JOIN
/ GROUP BY
.
Комментарии:
1. Большое вам спасибо за ответ… Можно ли также сделать это с помощью подзапроса?
Ответ №2:
Вы можете попробовать, присоединившись к таблицам, предпочитая делать JOIN
это, чем использовать SUBQUERY
SELECT user.*, count( post.user_id ) as postcount
FROM user LEFT JOIN post ON users.user_id = post.user_id
GROUP BY post.user_id
HAVING postcount > 10 ;
Комментарии:
1. Очень признателен за ответ! ^_^ можете ли вы сказать, можно ли сделать то же самое и с подзапросом? и почему в этом случае вы предпочли бы присоединиться к левым? Не будет ли он отображать ВСЕХ пользователей (где на самом деле проблема требует только тех пользователей, у которых более 10 сообщений)
2. Я отредактировал свой ответ, чтобы получить пользователей с количеством сообщений больше 10, Причина, по которой я предпочел присоединиться к left, заключалась в том, что вы получите всех пользователей, если нет сообщений (на основе моего предыдущего ответа, который сейчас не очень актуален).
The retrieval time of the query using joins almost always will be faster than that of a subquery
поэтому я бы предложил использовать join.