Нужно выбрать заказы, у которых amount выше среднего amount по тому же пользователю. Какой вариант WHERE корректно использует коррелированный подзапрос?
A
WHERE o.amount > (SELECT AVG(amount) FROM orders): подзапрос даёт одно глобальное среднее по всем заказамB
WHERE o.amount > (SELECT AVG(amount) FROM orders WHERE user_id = 123): среднее берётся по конкретному user_idC
WHERE o.amount > (SELECT AVG(o2.amount) FROM orders o2 WHERE o2.user_id = o.user_id): подзапрос связан через o.user_id внешнегоD
WHERE o.user_id IN (SELECT AVG(amount) FROM orders GROUP BY user_id): список средних сравнивается с user_id через INПравильный ответ. Коррелированный подзапрос ссылается на колонку внешнего запроса (например,
o.user_id), поэтому среднее считается отдельно для каждого пользователя.Разбор
В коррелированном варианте подзапрос ссылается на колонку внешней таблицы (o.user_id), поэтому среднее считается отдельно для каждой строки внешнего запроса — то есть для каждого пользователя. Некоррелированный подзапрос вычисляет одно глобальное значение и сравнивает его со всеми строками. Вариант с захардкоженным user_id = 123 ограничивает сравнение одним пользователем, а вариант с IN ломается логически: AVG(amount) сравнивается с user_id, что бессмысленно по типу.
Проверь себя · 1/3разбор после ответа
Вы разбираете сложный отчёт коллеги: 4 уровня вложенных подзапросов в
FROM без имён шагов. Решаете переписать через WITH. Какое практическое преимущество даёт CTE по сравнению с вложенными подзапросами?Ещё вопросы по теме «Подзапросы и CTE»
- В отчёте нужно посчитать выручку по странам пользователей только по оплаченным заказам за период, причём шаг «оплаченные за период» используется ещё в трёх соседних метриках. Какой подход обычно делает запрос проверяемее и позволяет переиспользовать фильтрацию?
- Вы выбираете пользователей, у которых есть хотя бы один платёж. В таблице `payments` поле `user_id` иногда бывает `NULL` (например, анонимные платежи). Почему в такой ситуации часто предпочитают `EXISTS`, а не `IN`?
- Вы пишете `SELECT u.user_id, (SELECT order_id FROM orders o WHERE o.user_id = u.user_id) AS last_order_id FROM users u`. Что может пойти не так и как исправить, чтобы подзапрос стал скалярным?
- Дашборд содержит две метрики на одних и тех же продажах: топ товаров по выручке за период и общая выручка за тот же период. Витрина обновляется ежедневно, и важно, чтобы фильтр по периоду был один и тот же для обеих цифр. Какой подход надёжнее защищает от рассинхронизации?
- Вы ищете пользователей без заказов запросом `SELECT u.user_id FROM users u WHERE u.user_id NOT IN (SELECT o.user_id FROM orders o)`. Почему он может вернуть 0 строк и какой подход безопаснее?
- Все вопросы по «Подзапросы и CTE» →