Нужно выбрать пользователей, у которых число заказов выше среднего по всем пользователям. Какой запрос корректно считает «среднее по пользователям», а не «среднее по заказам»?

ASELECT o.user_id FROM orders o GROUP BY o.user_id HAVING COUNT(*) > (SELECT AVG(COUNT(*)) FROM orders GROUP BY user_id)
BSELECT o.user_id FROM orders o GROUP BY o.user_id HAVING COUNT(*) > (SELECT AVG(amount) AS avg_amt FROM orders)
CWITH cnt AS (SELECT user_id, COUNT(*) AS o FROM orders GROUP BY user_id) SELECT user_id FROM cnt WHERE o > (SELECT AVG(o) FROM cnt)
DSELECT u.user_id FROM users u WHERE u.user_id IN (SELECT AVG(orders_cnt) FROM cnt GROUP BY user_id)
Правильный ответ. Нужно сначала агрегировать заказы до уровня пользователя, а затем считать среднее уже по этому уровню.

Разбор

Среднее по пользователям означает: для каждого пользователя считаем COUNT(*), получаем таблицу «пользователь → число заказов», и только потом берём AVG по этим значениям. Если пытаться посчитать среднее напрямую по таблице orders, легко перепутать уровень данных и получить другую метрику (например, среднее по строкам заказов). CTE помогает явно зафиксировать нужную гранулярность.

Проверь себя · 1/3разбор после ответа
В отчёте нужно посчитать выручку по странам пользователей только по оплаченным заказам за период, причём шаг «оплаченные за период» используется ещё в трёх соседних метриках. Какой подход обычно делает запрос проверяемее и позволяет переиспользовать фильтрацию?
Тренировать SQL в Telegram

Ещё вопросы по теме «Подзапросы и CTE»