📁 Блок: 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;