В SQL оконная функция или аналитическая функция [1] — это функция, которая использует значения из одной или нескольких строк для возврата значения для каждой строки. (Это контрастирует с агрегатной функцией , которая возвращает одно значение для нескольких строк.) Оконные функции имеют предложение OVER; любая функция без предложения OVER не является оконной функцией, а скорее агрегатной или однострочной (скалярной) функцией. [2]
В качестве примера приведем запрос, который использует оконную функцию для сравнения зарплаты каждого сотрудника со средней зарплатой его отдела (пример из документации PostgreSQL ): [3]
ВЫБРАТЬ depname , empno , salary , avg ( зарплата ) НАД ( РАЗДЕЛЕНИЕ ПО depname ) ИЗ empsalary ;
Выход:
depname | empno | salary | avg ----------+-------+--------+----------------------разработать | 11 | 5200 | 5020.00000000000000000разработать | 7 | 4200 | 5020.00000000000000000разработать | 9 | 4500 | 5020.00000000000000000разработать | 8 | 6000 | 5020.00000000000000000разработать | 10 | 5200 | 5020.00000000000000000персонал | 5 | 3500 | 3700.00000000000000000персонал | 2 | 3900 | 3700.00000000000000000продажи | 3 | 4800 | 4866.6666666666666667продажи | 1 | 5000 | 4866.6666666666666667продажи | 4 | 4800 | 4866.6666666666666667(10 рядов)
Предложение PARTITION BY
группирует строки в разделы, и функция применяется к каждому разделу отдельно. Если PARTITION BY
предложение опущено (например, с пустым OVER()
предложением), то весь набор результатов рассматривается как один раздел. [4] Для этого запроса средняя зарплата, указанная в отчете, будет средним значением, взятым по всем строкам.
Оконные функции оцениваются после агрегации ( GROUP BY
например, после предложения и неоконных агрегатных функций). [1]
Согласно документации PostgreSQL, оконная функция имеет один из следующих синтаксисов: [4]
имя_функции ([ выражение [, выражение ... ]]) OVER имя_окна имя_функции ([ выражение [, выражение ... ]]) OVER ( определение_окна ) имя_функции ( * ) OVER имя_окна имя_функции ( * ) OVER ( определение_окна )
где window_definition
есть синтаксис:
[ имя_существующего_окна ] [ выражение PARTITION BY [, ... ] ] [ выражение ORDER BY [ оператор ASC | DESC | USING ] [ NULLS { FIRST | LAST } ] [, ... ] ] [ предложение_рамки ]
frame_clause
имеет один из следующих синтаксисов:
{ ДИАПАЗОН | СТРОКИ | ГРУППЫ } начало_кадра [ исключение_кадра ] { ДИАПАЗОН | СТРОКИ | ГРУППЫ } МЕЖДУ началом_кадра И концом_кадра [ исключение_кадра ]
frame_start
и frame_end
может быть UNBOUNDED PRECEDING
, offset PRECEDING
, CURRENT ROW
, offset FOLLOWING
, или UNBOUNDED FOLLOWING
. frame_exclusion
может быть EXCLUDE CURRENT ROW
, EXCLUDE GROUP
, EXCLUDE TIES
, или EXCLUDE NO OTHERS
.
expression
относится к любому выражению, которое не содержит вызова оконной функции.
Обозначение:
Оконные функции позволяют получить доступ к данным в записях непосредственно перед и после текущей записи. [5] [6] [7] [8] Оконная функция определяет рамку или окно строк с заданной длиной вокруг текущей строки и выполняет вычисления по набору данных в окне. [9] [10]
ИМЯ |------------ Аарон| <-- Предшествующий (неограниченный) Эндрю| Амелия| Джеймс| Джилл| Джонни| <-- 1-й предыдущий ряд Майкл| <-- Текущая строка Ник| <-- 1-й следующий ряд Офелия| Зак| <-- Последующий (неограниченный)
В приведенной выше таблице следующий запрос извлекает для каждой строки значения окна с одной предыдущей и одной последующей строкой:
SELECT LAG ( имя , 1 ) OVER ( УПОРЯДОЧИТЬ ПО имени ) "предыдущий" , имя , LEAD ( имя , 1 ) OVER ( УПОРЯДОЧИТЬ ПО имени ) "следующий" FROM people УПОРЯДОЧИТЬ ПО имени
Результат запроса содержит следующие значения:
| ПРЕДЫДУЩАЯ | ИМЯ | СЛЕДУЮЩАЯ ||----------|----------|----------|| (null)| Аарон| Эндрю|| Аарон| Эндрю| Амелия|| Эндрю| Амелия| Джеймс|| Амелия| Джеймс| Джилл|| Джеймс| Джилл| Джонни|| Джилл| Джонни| Майкл|| Джонни| Майкл| Ник|| Майкл| Ник| Офелия|| Ник| Офелия| Зак|| Офелия| Зак| (null)|
Оконные функции были введены в стандарт SQL:2003 и имели расширенную функциональность в более поздних спецификациях. [11]
Была добавлена поддержка для конкретных реализаций баз данных следующим образом: