← К оглавлению занятия

🐛 Типичные ошибки

📁 Блок: SQL / MySQL / Оконные функции ⏱️ Время изучения: ~60 мин 🎯 Сложность: Повторение

⚡ Кратко: ошибки

  • Фильтровать по псевдониму оконной функции в WHERE.
  • Добавлять GROUP BY рядом с оконной функцией без нужды.
  • Забывать ORDER BY, когда нужна кумулятивная сумма.
  • Путать COUNT(*) и COUNT(column).
  • Считать, что кумулятивная сумма работает только с датами.
1

Ошибка: фильтрация по результату оконной функции в WHERE

Оконные функции вычисляются после WHERE, поэтому их псевдоним нельзя использовать в фильтре.

-- Неправильно
SELECT
    order_id,
    SUM(quantity * unit_cost) OVER (PARTITION BY order_id) AS order_total
FROM purchase_order_details
WHERE order_total > 1000;

Как исправить: оберните запрос в подзапрос или используйте QUALIFY (где поддерживается).

-- Правильно
SELECT *
FROM (
    SELECT
        order_id,
        SUM(quantity * unit_cost) OVER (PARTITION BY order_id) AS order_total
    FROM purchase_order_details
) sub
WHERE order_total > 1000;
2

Ошибка: лишний GROUP BY рядом с оконной функцией

GROUP BY сворачивает строки, поэтому совместное использование с оконной функцией часто приводит к ошибке или потере данных.

-- Неправильно
SELECT
    order_id,
    product_id,
    COUNT(*) OVER (PARTITION BY order_id)
FROM purchase_order_details
GROUP BY order_id;

Как исправить: уберите GROUP BY, если нужно сохранить детальные строки.

-- Правильно
SELECT
    order_id,
    product_id,
    COUNT(*) OVER (PARTITION BY order_id) AS products_count
FROM purchase_order_details;
3

Ошибка: отсутствие ORDER BY при кумулятивном расчёте

Без ORDER BY функция вернёт одну общую сумму, а не накопительную.

-- Неправильно: одинаковое значение во всех строках
SELECT
    purchase_order_id,
    date_received,
    SUM(quantity) OVER () AS wrong_cumulative
FROM purchase_order_details;

Как исправить: добавьте ORDER BY в окно.

-- Правильно
SELECT
    purchase_order_id,
    date_received,
    SUM(quantity) OVER (ORDER BY date_received) AS cumulative_quantity
FROM purchase_order_details;
4

Ошибка: COUNT(column) вместо COUNT(*)

COUNT(product_id) не посчитает строки с NULL в product_id, а COUNT(*) посчитает все строки окна.

-- Может дать меньшее значение, если product_id содержит NULL
SELECT
    order_id,
    product_id,
    COUNT(product_id) OVER (PARTITION BY order_id) AS cnt
FROM purchase_order_details;

-- Правильно, если нужно число всех строк группы
SELECT
    order_id,
    product_id,
    COUNT(*) OVER (PARTITION BY order_id) AS cnt
FROM purchase_order_details;
5

Ошибка: кумулятивная сумма только с датами

В конспекте сказано, что кумулятивные значения рассчитываются «только при использовании столбца с датами». Это неточность: ORDER BY в окне может ссылаться на любой столбец.

-- Тоже корректно: накопление по числовому идентификатору
SELECT
    purchase_order_id,
    quantity,
    SUM(quantity) OVER (ORDER BY purchase_order_id) AS cumulative_quantity
FROM purchase_order_details;