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

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

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

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

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

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

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

-- Неправильно
SELECT
    order_id,
    customer_id,
    SUM(order_amount) OVER (PARTITION BY customer_id) AS total
FROM orders
WHERE total > 1000;

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

-- Правильно
SELECT *
FROM (
    SELECT
        order_id,
        customer_id,
        SUM(order_amount) OVER (PARTITION BY customer_id) AS total
    FROM orders
) sub
WHERE total > 1000;
2

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

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

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

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

-- Правильно
SELECT
    product_name,
    category,
    COUNT(*) OVER (PARTITION BY category) AS products_in_category
FROM products;
3

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

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

-- Неправильно: одинаковое значение во всех строках
SELECT
    sale_id,
    sale_date,
    SUM(sale_amount) OVER () AS wrong_cumulative
FROM sales;

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

-- Правильно
SELECT
    sale_id,
    sale_date,
    SUM(sale_amount) OVER (ORDER BY sale_date) AS cumulative_sales
FROM sales;
4

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

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

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

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