Является ли partition by обязательным аргументом в оконных функциях SQL?
Что проверяют
Понимание оконных функций дальше заученного шаблона. Аналитик пишет их каждый день, и вопрос разделяет тех, кто копирует конструкцию из готового запроса, и тех, кто понимает, что такое окно и рамка.
Как отвечать
Нет, не обязателен. В скобках OVER необязательно ничего: ни секционирование, ни сортировка, ни рамка. Пустые скобки означают одно окно на весь результат.
select
city,
sum(amount) over () as total_all,
sum(amount) over (partition by city) as total_city
from ordersСкажите, чем секционирование отличается от группировки: строки не схлопываются, к каждой добавляется значение, посчитанное по её группе.
Дальше та часть, которая отличает уверенный ответ. Без сортировки рамка по умолчанию покрывает всю секцию. Как только появляется ORDER BY, рамка становится накопительной, от начала секции до текущей строки, причём строки с одинаковым значением сортировки попадают в неё целиком. Отсюда неожиданные одинаковые суммы на дублях ключа; лечится переходом с RANGE на ROWS.
Стоит добавить два факта. Ранжирующим функциям сортировка нужна по смыслу, а в ряде диалектов ещё и обязательна синтаксически. И оконные функции вычисляются после WHERE и GROUP BY, поэтому фильтровать по их результату там нельзя: нужен подзапрос, общее табличное выражение или QUALIFY, если диалект его поддерживает.
Где спотыкаются
Считают секционирование обязательным и пишут его по константе, чтобы формально заполнить конструкцию. Лишняя группировка по одному значению не меняет результат, зато мешает планировщику и путает читателя.
Получают накопительный итог вместо общей суммы и не связывают это с рамкой по умолчанию, добавленной вместе с сортировкой. Ищут ошибку в данных, хотя запрос делает ровно то, что написано.
Пробуют отфильтровать по оконной функции прямо в WHERE или HAVING, получают ошибку и решают, что в базе чего-то не хватает. Порядок вычисления такой фильтр исключает, обёртка подзапросом решает задачу.