Использовать GROUP BY там, где нужна оконная функция.
Забывать, что оконные функции вычисляются после WHERE, но перед ORDER BY результата.
1
Ошибка: смешивание ORDER BY в окне и ORDER BY результата
Новички часто думают, что ORDER BY внутри OVER влияет на порядок строк в выводе.
-- Неправильное ожидание: результат отсортирован по salary
SELECT
employee_id,
department_id,
salary,
AVG(salary) OVER (PARTITION BY department_id ORDER BY salary)
FROM employees;
Как исправить: если нужна сортировка результата, добавьте ORDER BY в конец запроса.
-- Правильно
SELECT
employee_id,
department_id,
salary,
AVG(salary) OVER (PARTITION BY department_id)
FROM employees
ORDER BY department_id, salary;
2
Ошибка: лишнее GROUP BY рядом с оконной функцией
Использование GROUP BY вместе с оконной функцией без необходимости приводит к ошибкам или потере строк.
-- Неправильно: GROUP BY сворачивает строки, оконная функция уже не нужна
SELECT
employee_id,
department_id,
COUNT(*) OVER (PARTITION BY department_id)
FROM employees
GROUP BY department_id;
Как исправить: уберите GROUP BY, если нужно сохранить все строки.
-- Правильно
SELECT
employee_id,
department_id,
COUNT(*) OVER (PARTITION BY department_id) AS dept_count
FROM employees;
3
Ошибка: ожидание, что PARTITION BY обязателен
Некоторые думают, что без PARTITION BY оконная функция не работает. На самом деле OVER () задаёт окно из всех строк.
-- Правильно: окно охватывает все строки
SELECT
employee_id,
salary,
SUM(salary) OVER () AS total_salary
FROM employees;
4
Ошибка: использование псевдонима оконной функции в WHERE
Оконные функции вычисляются после фильтрации WHERE, поэтому их псевдоним нельзя использовать в WHERE.
-- Неправильно
SELECT
employee_id,
department_id,
COUNT(*) OVER (PARTITION BY department_id) AS dept_count
FROM employees
WHERE dept_count > 5;
Как исправить: используйте подзапрос или QUALIFY (в некоторых СУБД).
-- Правильно: подзапрос
SELECT *
FROM (
SELECT
employee_id,
department_id,
COUNT(*) OVER (PARTITION BY department_id) AS dept_count
FROM employees
) sub
WHERE dept_count > 5;