Как выполнить подзапрос в SQL (SELECT с передачей параметра из основного запроса?
Подскажите, как решить такую задачу.
Условно, есть таблица Users
id, name
Есть таблица Orders
id, number, user_id
Я хочу через подзапрос посчитать кол-во заказов по каждому пользователю.
Что-то вроде
select users.name as username,
(select count(id) from orders where user_id=users.id) as orders_count
from users
Насколько я понимаю, т.к. подзапросы выполняются снизу вверх, то users.id не получиться передать в подзапрос.
Да, можно сделать join, но с ним проблема у меня, т.к. в моем случае он уже там есть по другим критериям с этими же таблицами, по которым я хочу посчитать данные, в общем нужен какой другой механизм. Т.е.
Насколько я понимаю, т.к. подзапросы выполняются снизу вверх
Нет.
можно сделать join, но с ним проблема у меня, т.к. в моем случае он уже там есть по другим критериям с этими же таблицами, по которым я хочу посчитать данные
Это не может быть проблемой. В крайнем случае, если вылезает join multiplying, подсчёт может быть убран в CTE/подзапрос. Впрочем, скорее всего orders.id - синтетический первичный ключ, тогда COUNT(DISTINCT orders.id) снимает эту проблему.
select u.name as username,
(select count(id) from orders where user_id=u.id) as orders_count
from users u
Добавляем псевдоним для таблицы users. Так должно сработать.
Но вариант не очень, предполагаю, что зная все условия, можно придумать более производительное решение.
Akina, прямо таки вообще-вообще?
Поскольку речь шла об условных данных и неуказанных JOIN'ах по другим критериям, я предположил, что запросу в посте мешают выполняться ошибки "ambiguous column name". Других видимых проблем в исходном запросе нет.
я предположил, что запросу в посте мешают выполняться ошибки "ambiguous column name".
В показанном запросе нет оснований для неоднозначности, даже если имеются одноимённые поля. При отсутствии алиаса таблицы в подзапросе поле берётся из источника данных подзапроса, либо возникает ошибка "неизвестное поле" - т.е. без алиаса внешней для подзапроса таблицы поле не будет искаться "снаружи" подзапроса ни при каких обстоятельствах (даже если LATERAL).
SELECT users.name AS username,
count(orders.id) AS orders_count
FROM users
JOIN orders ON orders.user_id=users.id
GROUP BY users.name
Если нужно вывести и пользователей, у которых нет заказов, с нулевым количеством, то использовать LEFT JOIN.
PS. Запрос из текста вопроса тоже корректен и должен дать правильный результат. Причём с 50% вероятностью он будет преобразован в мой (точнее, оба дадут один и тот же план выполнения). Остальные 50% - на то, что он будет выполнен итерационно (и тогда скорее всего просто будет выполняться дольше).
Только надо иметь в виду - если, как написал автор вопроса, JOIN orders уже используется для получения других данных - списка заказов пользователя, например, то этот список у пользователя "схлопнется" в одну позицию.