Читать книгу SQL для аналитика. 50 задач с решениями на PostgreSQL - Ар'лан ис'Дрекхэм - Страница 13

Часть 2. Продуктовая аналитика
Глава 11. DATE_TRUNC, SUM, кросс-таблицы. Выручка по месяцам

Оглавление

Описание задачи

Новый отчёт: посчитаем общую выручку по месяцам на основе завершённых заказов. А затем представим эти данные в виде кросс-таблицы, где месяцы – строки, а категории товаров – колонки.

Таблицы: orders, order_items, products, categories.

Основные SQL-конструкции

DATE_TRUNC – обрезает дату до указанной точности (год, месяц, день, час).

text

DATE_TRUNC (’month’, order_date) /* 2024-01-15 → 2024-01-01 */


SUM – агрегатная функция, суммирует значения (см. главу 10).


crosstab – функция из расширения PostgreSQL tablefunc. Превращает строки в колонки. В функцию передаётся в кавычках запрос, который нам надо перевернуть.

Для использования crosstab нужно установить расширение:

text

CREATE EXTENSION IF NOT EXISTS tablefunc;


Совет

DATE_TRUNC удобен для группировки по периодам: неделям, месяцам, кварталам, годам.

SQL-запросы с объяснением

Задача 1. Выручка по месяцам.

text

SELECT

DATE_TRUNC (’month’, order_date) AS month,

SUM (oi. quantity * oi.price_per_unit) AS revenue

FROM orders o

JOIN order_items oi ON o. order_id = oi. order_id

WHERE o.status = ’completed’

GROUP BY DATE_TRUNC (’month’, order_date)

ORDER BY month;

Как это работает

– DATE_TRUNC (’month’, order_date) – превращает дату в первый день месяца.

– JOIN – соединяем заказы с их товарами.

– SUM – считаем общую выручку.

– GROUP BY – группируем по месяцам.

– ORDER BY month – сортируем по возрастанию.


Пример вывода (фрагмент):

text

month revenue

2024-01-01 00:00:00+03 1571090.00

2024-02-01 00:00:00+03 1458330.00

2024-03-01 00:00:00+03 1407930.00

2024-04-01 00:00:00+03 1193490.00


Задача 2. Выручка по месяцам и категориям (обычный GROUP BY).

Подготовим данные для кросс-таблицы: выручка по месяцам и категориям.

text

SELECT

DATE_TRUNC (’month’, o. order_date) AS month,

c.name AS category_name,

SUM (oi. quantity * oi.price_per_unit) AS revenue

FROM orders o

JOIN order_items oi ON o. order_id = oi. order_id

JOIN products p ON oi.product_id = p.product_id

JOIN categories c ON p.category_id = c.category_id

WHERE o.status = ’completed’

GROUP BY month, c.category_id, c.name

ORDER BY month, category_name;


Как это работает

– Группируем по месяцу и категории.

– Считаем выручку для каждой пары (месяц, категория).

Пример вывода (фрагмент):

text

month category_name revenue

2024-01-01 00:00:00+03 Женская 11970.00

2024-01-01 00:00:00+03 Мужская 11970.00

2024-01-01 00:00:00+03 Наушники 79700.00

2024-01-01 00:00:00+03 Ноутбуки 689600.00

2024-01-01 00:00:00+03 Планшеты 69900.00


Задача 3. Кросс-таблица: месяцы в строках, категории в колонках.

Превращаем результат задачи 2 в таблицу, где категории становятся колонками, используем crosstab из расширения tablefunc.

text

CREATE EXTENSION IF NOT EXISTS tablefunc;


SELECT * FROM crosstab (

«SELECT

DATE_TRUNC (»’month’», o. order_date)::date AS month,

c.name AS category_name,

SUM (oi. quantity * oi.price_per_unit) AS revenue

FROM orders o

JOIN order_items oi ON o. order_id = oi. order_id

JOIN products p ON oi.product_id = p.product_id

JOIN categories c ON p.category_id = c.category_id

WHERE o.status = '’completed’'/*выполнено*/

GROUP BY month, c.category_id, c.name

ORDER BY 1,2»,

«SELECT DISTINCT name FROM categories WHERE name IN (»«Ноутбуки»», ««Смартфоны»», ««Планшеты»») ORDER BY 1»)

AS ct (month date, «Ноутбуки» numeric, «Смартфоны» numeric, «Планшеты» numeric);


Как это работает

– Первый запрос – данные: месяц, категория, выручка.

– Второй запрос – список категорий, которые станут колонками.

– crosstab превращает строки в колонки AS ct (month date, «Ноутбуки» numeric, «Смартфоны» numeric, «Планшеты» numeric).

– ::date – преобразуем timestamp в дату.

– Кавычки в названиях колонок нужны из-за русских букв.

– Две одинарные кавычки подряд используются для экранирования кавычек внутри строки crosstab.

результат

«2024-01-01» 689600.00 69900.00 699000.00

«2024-02-01» 489500.00 209700.00 594200.00

«2024-03-01» 799400.00 209700.00 354500.00

«2024-04-01» 614400.00 69900.00 449400.00

«2024-05-01» 89900.00 null 154800.00


Вопросы и ответы

В: Зачем нужна кросс-таблица?

О: Она компактно показывает данные: строки – месяцы, колонки – категории. Удобно для отчётов и дашбордов.


В: Почему во втором запросе crosstab указаны не все категории?

О: Чтобы колонок было не слишком много. В реальных отчётах выбирают топ-5 или топ-10 категорий.


В: Что делать, если в какой-то месяц не было продаж по категории?

О: В примере выше будет 0.00 или NULL.


В: Можно ли использовать crosstab без второго запроса?

О: Да, но тогда категории нужно перечислить вручную в определении колонок, а запрос должен возвращать данные в строгом порядке.

Что в итоге

Мы научились:

– Группировать данные по месяцам с DATE_TRUNC

– Считать выручку по месяцам и категориям

– Строить кросс-таблицы с помощью crosstab

Кросс-таблицы удобны для отчётов, где нужно сравнить показатели по разным категориям в динамике.

* Задание со звёздочкой

Напишите запрос, который строит кросс-таблицу выручки по кварталам (используйте DATE_TRUNC (’quarter’, order_date)) и категориям «Ноутбуки», «Смартфоны», «Планшеты».

Подсказка: замените ’month’ на ’quarter’ в первом запросе crosstab.

SQL для аналитика. 50 задач с решениями на PostgreSQL

Подняться наверх