Задачи на агрегатные функции SQL
Агрегаты·junior

Топ-5 клиентов по выручке

Задача

Ты аналитик в сети видеопроката (да, ещё остались такие). Менеджер просит: «Дай топ-5 клиентов по сумме платежей — хотим им предложить персональную скидку, чтобы не ушли к конкурентам».

Нужен список из 5 клиентов с максимальной суммарной выручкой: имя, фамилия и сумма.

Схема данных

Работаем с учебной базой проката фильмов dvdrental. Тебе понадобятся две таблицы:

  • customer(customer_id, first_name, last_name, ...) — клиенты.
  • payment(payment_id, customer_id, amount, payment_date, ...) — платежи; один клиент может встречаться много раз.

Связь простая: payment.customer_id ссылается на customer.customer_id.

Решение

SELECT c.first_name, c.last_name, sum(p.amount) AS revenue
FROM payment p
JOIN customer c USING (customer_id)
GROUP BY c.customer_id, c.first_name, c.last_name
ORDER BY revenue DESC
LIMIT 5;

Разбор

Первая мысль у джуна обычно такая: «сложить amount по customer_id» — и это правильная мысль, вопрос только в деталях.

Джойн через USING (customer_id) — сокращённая форма ON p.customer_id = c.customer_id, работает, когда имя колонки совпадает в обеих таблицах. Дальше — GROUP BY: в него нужно положить не только customer_id, но и first_name/last_name, иначе PostgreSQL честно скажет column "c.first_name" must appear in the GROUP BY clause — движок не может угадать, какое из имён показывать для группы, даже если по факту оно одно на группу.

SUM(p.amount) считает суммарную выручку по группе — именно то, что просил менеджер, а не средний чек (для него была бы AVG). Дальше ORDER BY revenue DESC — сортируем по алиасу агрегата, PostgreSQL это разрешает в отличие от WHERE. И LIMIT 5 — берём только первую пятёрку.

Частая ошибка — попытаться отфильтровать топ через WHERE revenue > ...: WHERE выполняется до группировки, агрегат там ещё не существует. Если бы нужно было отсечь клиентов с выручкой меньше порога уже после группировки — использовали бы HAVING, но здесь достаточно ORDER BY + LIMIT.

Похожая логика группировки разбирается в задаче «сколько фильмов длиннее двух часов» — там, правда, агрегат без группировки, на всю таблицу целиком.

Ожидаемый результат

first_name | last_name | revenue
--- | --- | ---
Eleanor | Hunt | 211.55
Karl | Seal | 208.58
Marion | Snyder | 194.61
Rhonda | Kennedy | 191.62
Clara | Shaw | 189.60

Прорешай такие задачи сам

Читать разбор полезно, а настоящая прокачка — самому писать запросы и получать обратную связь. В симуляторе живая база и проверка запросов, лёгкий режим — бесплатно.

Прорешать в бесплатной песочнице

Смежные задачи

Вопросы по теме