SQL: Топ-5 продуктов по выручке
Условие
Дана таблица продаж с полями: product_name, quantity, price.
Напишите SQL-запрос для поиска топ-5 продуктов по общей выручке.
Используйте группировку, агрегацию и сортировку.
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Базовый запрос: Топ-5 по выручке
SELECT
product_name,
SUM(quantity * price) AS total_revenue
FROM sales
GROUP BY product_name
ORDER BY total_revenue DESC
LIMIT 5;
Объяснение:
SUM(quantity * price)— рассчитываем выручку как произведение количества и ценыGROUP BY product_name— группируем данные по названию продуктаORDER BY total_revenue DESC— сортируем по выручке в убывающем порядкеLIMIT 5— берём только первые 5 строк
Вариант 2: С дополнительной статистикой
Часто нужна не только выручка, но и другие метрики:
SELECT
product_name,
COUNT(*) AS number_of_sales,
SUM(quantity) AS total_quantity,
ROUND(AVG(price), 2) AS avg_price,
SUM(quantity * price) AS total_revenue,
ROW_NUMBER() OVER (ORDER BY SUM(quantity * price) DESC) AS rank
FROM sales
GROUP BY product_name
ORDER BY total_revenue DESC
LIMIT 5;
Новые элементы:
COUNT(*)— количество транзакцийSUM(quantity)— общее количество единицAVG(price)— средняя цена продуктаROW_NUMBER() OVER (ORDER BY ...)— ранг для визуализации позиции
Вариант 3: С фильтрацией по дате
В реальных задачах часто нужны данные за конкретный период:
SELECT
product_name,
SUM(quantity * price) AS total_revenue
FROM sales
WHERE sale_date >= DATE_TRUNC('month', CURRENT_DATE) - INTERVAL '1 month'
GROUP BY product_name
ORDER BY total_revenue DESC
LIMIT 5;
Вариант 4: Со скользящим окном
Для анализа трендов:
WITH ranked_sales AS (
SELECT
product_name,
sale_date,
quantity * price AS revenue,
SUM(quantity * price) OVER (
PARTITION BY product_name
ORDER BY sale_date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS moving_avg_7days
FROM sales
)
SELECT
product_name,
SUM(revenue) AS total_revenue,
ROUND(AVG(moving_avg_7days), 2) AS avg_7day_moving_avg
FROM ranked_sales
GROUP BY product_name
ORDER BY total_revenue DESC
LIMIT 5;
Вариант 5: С процентом от общей выручки
WITH product_revenue AS (
SELECT
product_name,
SUM(quantity * price) AS total_revenue
FROM sales
GROUP BY product_name
),
total_revenue_calc AS (
SELECT SUM(total_revenue) AS grand_total FROM product_revenue
)
SELECT
pr.product_name,
pr.total_revenue,
ROUND(100.0 * pr.total_revenue / tr.grand_total, 2) AS revenue_percentage,
ROW_NUMBER() OVER (ORDER BY pr.total_revenue DESC) AS rank
FROM product_revenue pr
CROSS JOIN total_revenue_calc tr
ORDER BY pr.total_revenue DESC
LIMIT 5;
Ключевые элементы SQL-запроса
GROUP BY — группирует строки по одному или нескольким столбцам. Без этого агрегатные функции работали бы на всей таблице.
Агрегатные функции:
SUM()— сумма значенийCOUNT()— количество строкAVG()— среднее значениеMIN(),MAX()— минимум и максимум
ORDER BY — сортирует результаты. DESC = по убыванию, ASC = по возрастанию.
LIMIT — ограничивает количество возвращаемых строк.
Window Functions — позволяют выполнять расчёты в окне строк без потери деталей.
Оптимизация для больших таблиц
Для таблиц с миллионами строк:
SELECT
product_name,
SUM(quantity * price) AS total_revenue
FROM sales
WHERE sale_date >= CURRENT_DATE - INTERVAL '1 year'
GROUP BY product_name
ORDER BY total_revenue DESC
LIMIT 5;
Рекомендации:
- Используй WHERE ДО GROUP BY для фильтрации
- Создавай индексы на
product_nameиsale_date - Для больших датасетов рассмотри материализованные представления