Основные оконные функции

В предыдущих статьях мы рассмотрели, как работают оконные функции, познакомились с понятием окна данных, которое передаётся в оконную функцию. Пришло время рассмотреть какие оконные функции бывают.

Виды оконных функций

Категории оконных функций

Оконные функции можно разделить на 3 группы:

  • Агрегатные оконные функции
  • Ранжирующие оконные функции
  • Оконные функции смещения

Агрегатные оконные функции

Агрегатные функции — это функции, которые выполняют на наборе данных арифметические вычисления и возвращают итоговое значение.

  • SUM — подсчитывает общую сумму значений;
  • COUNT — считает общее количество записей в колонке;
  • AVG — рассчитывает среднее арифметическое;
  • MAX — находит наибольшее значение;
  • MIN — определяет наименьшее значение.
MySQL 8.1
SELECT id,
	home_type,
	price,
	SUM(price) OVER(PARTITION BY home_type) AS "Sum",
	COUNT(price) OVER(PARTITION BY home_type) AS "Count",
	AVG(price) OVER(PARTITION BY home_type) AS "Avg",
	MAX(price) OVER(PARTITION BY home_type) AS "Max",
	MIN(price) OVER(PARTITION BY home_type) AS "Min"
FROM Rooms;
idhome_typepriceSumCountAvgMaxMin
2Entire home/apt225312221148.666729980
30Entire home/apt180312221148.666729980
28Entire home/apt150312221148.666729980
38Entire home/apt85312221148.666729980
25Entire home/apt120312221148.666729980
42Entire home/apt120312221148.666729980
21Entire home/apt299312221148.666729980
20Entire home/apt190312221148.666729980
19Entire home/apt99312221148.666729980
17Entire home/apt215312221148.666729980
16Entire home/apt140312221148.666729980
15Entire home/apt120312221148.666729980
46Entire home/apt150312221148.666729980
11Entire home/apt135312221148.666729980
10Entire home/apt150312221148.666729980
48Entire home/apt110312221148.666729980
49Entire home/apt115312221148.666729980
6Entire home/apt200312221148.666729980
45Entire home/apt150312221148.666729980
5Entire home/apt80312221148.666729980
4Entire home/apt89312221148.666729980
41Private room6825042889.428615035
34Private room5025042889.428615035
35Private room7025042889.428615035
50Private room8025042889.428615035
36Private room8925042889.428615035
1Private room14925042889.428615035
37Private room3525042889.428615035
39Private room15025042889.428615035
47Private room13025042889.428615035
43Private room12025042889.428615035
44Private room13525042889.428615035
22Private room13025042889.428615035
3Private room15025042889.428615035
7Private room6025042889.428615035
8Private room7925042889.428615035
9Private room7925042889.428615035
12Private room8525042889.428615035
13Private room8925042889.428615035
14Private room8525042889.428615035
18Private room14025042889.428615035
18Private room14025042889.428615035
33Private room5525042889.428615035
23Private room8025042889.428615035
24Private room11025042889.428615035
26Private room6025042889.428615035
27Private room8025042889.428615035
29Private room4425042889.428615035
31Private room5025042889.428615035
32Private room5225042889.428615035
40Shared room40401404040

Ранжирующие оконные функции

Ранжирующие оконные функции — это функции, которые ранжируют значение для каждой строки в окне.

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

  • ROW_NUMBER — возвращает номер строки, используется для нумерации;
  • RANK — возвращает ранг каждой строки. Вот как это работает:
    • Сортировка: во-первых, строки сортируются по одному или нескольким столбцам. Эти столбцы указываются в ORDER BY в конструкции OVER.
    • Присвоение рангов: каждой уникальной строке или группе строк, имеющих одинаковые значения в столбцах сортировки, присваивается ранг. Ранг начинается с 1.
    • Одинаковые значения: если у нескольких строк одинаковые значения в столбцах сортировки, они получают одинаковый ранг. Например, если две строки занимают второе место, обе получают ранг 2.
    • Пропуск рангов: после группы строк с одинаковым рангом, следующий ранг увеличивается на количество строк в этой группе. Например, если две строки имеют ранг 2, следующая строка получит ранг 4, а не 3.
    • Продолжение сортировки: этот процесс продолжается до тех пор, пока не будут присвоены ранги всем строкам в наборе результатов.
  • DENSE_RANK — возвращает ранг каждой строки. Но в отличие от функции RANK, она не пропускает ранги и после группы одинаковых значений ранг увеличивается на единицу, а не на количество строк. Например, если две строки имеют ранг 2, следующая строка получит ранг 3, а не 4.
MySQL 8.1
SELECT id,
	home_type,
	price,
	ROW_NUMBER() OVER(PARTITION BY home_type ORDER BY price) AS "row_number",
	RANK() OVER(PARTITION BY home_type ORDER BY price) AS "rank",
	DENSE_RANK() OVER(PARTITION BY home_type ORDER BY price) AS "dense_rank"
FROM Rooms;
idhome_typepricerow_numberrankdense_rank
5Entire home/apt80111
38Entire home/apt85222
4Entire home/apt89333
19Entire home/apt99444
48Entire home/apt110555
49Entire home/apt115666
25Entire home/apt120777
15Entire home/apt120877
42Entire home/apt120977
11Entire home/apt13510108
16Entire home/apt14011119
28Entire home/apt150121210
10Entire home/apt150131210
45Entire home/apt150141210
46Entire home/apt150151210
30Entire home/apt180161611
20Entire home/apt190171712
6Entire home/apt200181813
17Entire home/apt215191914
2Entire home/apt225202015
21Entire home/apt299212116
37Private room35111
29Private room44222
34Private room50333
31Private room50433
32Private room52554
33Private room55665
26Private room60776
7Private room60876
41Private room68997
35Private room7010108
8Private room7911119
9Private room7912119
27Private room80131310
23Private room80141310
50Private room80151310
12Private room85161611
14Private room85171611
13Private room89181812
36Private room89191812
24Private room110202013
43Private room120212114
22Private room130222215
47Private room130232215
44Private room135242416
18Private room140252517
1Private room149262618
3Private room150272719
39Private room150282719
40Shared room40111

Оконные функции смещения

Оконные функции смещения — это функции, которые позволяют перемещаться и обращаться к разным строкам в окне, относительно текущей строки, а также обращаться к значениям в начале или в конце окна.

  • LAG — обращается к данным из предыдущих строк окна.

    Имеет три аргумента: столбец, значение которого необходимо вернуть, количество строк для смещения (по умолчанию 1), значение, которое необходимо вернуть, если после смещения возвращается значение NULL.

  • LEAD — обращается к данным из следующих строк. Аналогично LAG имеет 3 аргумента.

  • FIRST_VALUE — возвращает первое значение в окне. В качестве аргумента принимает столбец, значение которого необходимо вернуть.

  • LAST_VALUE — возвращает последнее значение в окне. В качестве аргумента принимает столбец, значение которого необходимо вернуть

    При использовании ORDER BY рамки окна по умолчанию устанавливаются от начала партиции до текущей строки (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW). Из-за этого LAST_VALUE будет возвращать значение текущей строки, а не последней строки всей партиции. Чтобы получить действительно последнее значение партиции, необходимо явно расширить границы окна: ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.

MySQL 8.1
SELECT id,
	home_type,
	price,
	LAG(price) OVER(PARTITION BY home_type ORDER BY price) AS "lag",
	LAG(price, 2) OVER(PARTITION BY home_type ORDER BY price) AS "lag_2",
	LEAD(price) OVER(PARTITION BY home_type ORDER BY price) AS "lead",
	FIRST_VALUE(price) OVER(PARTITION BY home_type ORDER BY price) AS "first_value",
	LAST_VALUE(price) OVER(PARTITION BY home_type ORDER BY price ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS "last_value"
FROM Rooms;
idhome_typepricelaglag_2leadfirst_valuelast_value
5Entire home/apt80<NULL><NULL>8580299
38Entire home/apt8580<NULL>8980299
4Entire home/apt8985809980299
19Entire home/apt99898511080299
48Entire home/apt110998911580299
49Entire home/apt1151109912080299
25Entire home/apt12011511012080299
15Entire home/apt12012011512080299
42Entire home/apt12012012013580299
11Entire home/apt13512012014080299
16Entire home/apt14013512015080299
28Entire home/apt15014013515080299
10Entire home/apt15015014015080299
45Entire home/apt15015015015080299
46Entire home/apt15015015018080299
30Entire home/apt18015015019080299
20Entire home/apt19018015020080299
6Entire home/apt20019018021580299
17Entire home/apt21520019022580299
2Entire home/apt22521520029980299
21Entire home/apt299225215<NULL>80299
37Private room35<NULL><NULL>4435150
29Private room4435<NULL>5035150
34Private room5044355035150
31Private room5050445235150
32Private room5250505535150
33Private room5552506035150
26Private room6055526035150
7Private room6060556835150
41Private room6860607035150
35Private room7068607935150
8Private room7970687935150
9Private room7979708035150
27Private room8079798035150
23Private room8080798035150
50Private room8080808535150
12Private room8580808535150
14Private room8585808935150
13Private room8985858935150
36Private room89898511035150
24Private room110898912035150
43Private room1201108913035150
22Private room13012011013035150
47Private room13013012013535150
44Private room13513013014035150
18Private room14013513014935150
1Private room14914013515035150
3Private room15014914015035150
39Private room150150149<NULL>35150
40Shared room40<NULL><NULL><NULL>4040