День семьсот девяносто шестой. #ЗаметкиНаПолях #SQL
Ограничение Результатов с Помощью Оконных Функций
Оконные (window) аналитические функции давно присутствуют в SQL, однако многие до сих пор не умеют их применять.
Окно (window) - это набор строк таблицы, которые можно анализировать или применить к ним функцию. Строки должны быть как-то связаны. Иногда они связаны с конкретной строкой, т.е. строки могут быть выше или ниже друг друга или в пределах заданного диапазона. Либо связь может быть основана на отдельных группах данных в наборе.
Все оконные функции следуют определенному синтаксису.
<название функции>(<выражение>) OVER (
<окно>
<сортировка>
)
Сначала идёт название функции, а за ним следует предложение
OVER. Оно определяет область действия окна, указывая набор строк, к которым будет применяться функция. Предложение
OVER является обязательной частью оконной функции. Остальной синтаксис является необязательным, и зависит от желаемой области действия:
- Выражение
PARTITION BY можно использовать для разделения набора данных на отдельные группы (аналогично
GROUP BY).
- Выражение
ORDER BY используется для упорядочивания строк в каждой группе.
В качестве оконных можно использовать простые агрегатные функции, вроде
SUM(),
COUNT(),
AVG() и т.п. Но есть и несколько специальных.
Номера и ранг строк
Простейший вариант применения оконной функции – вывести номера строк результата (см.
пример 1 на картинке ниже). Здесь «окном» является весь набор, а функция
ROW_NUMBER() выводит номер строки по порядку.
Мы можем разделить набор данных на группы, используя
PARTITION BY. В
примере 2 на картинке ниже тот же набор разделён по полю
name, а внутри каждой такой группы упорядочен по полю
course.
Кроме этого две функции
RANK() и
DENSE_RANK() выводят ранг строки. Они отличаются от
ROW_NUMBER() тем, что при равенстве результатов задают строкам одинаковые значения. При этом
DENSE_RANK() продолжает нумерацию, например,
1,1,2,2,3. А
RANK() использует следующий номер строки по порядку, оставляя разрывы в нумерации:
1,1,3,3,5. В
примере 3 на картинке ниже приводится сравнение этих функций на том же наборе данных. Здесь использована сортировка всего набора по полю name, без разбиения на группы.
Заметьте, что выражение
ORDER BY внутри оконной функции никак не связано с выражением
ORDER BY всего запроса. Оно влияет только на результаты оконной функции. В предыдущем примере мы могли бы добавить
ORDER BY ко всему запросу и изменить порядок строк в запросе, но результаты функций
ROW_NUMBER(),
RANK() и
DENSE_RANK() в строках не изменились бы.
Первое и последнее значение
Эти функции позволяют вывести первое или последнее соответственно значение столбца в группе. В отличие от функций, описанных выше, для каждой группы будет выведена только одна строка. Например, если использовать
LAST_VALUE(course) на наборе данных из примера 2(последний по алфавиту курс для каждого студента), то будет выведено 3 строки:
Jason Economics
Lucy Health Science
Martha Biology.
Предыдущие и последующие строки
Часто бывает полезно сравнивать строки с предыдущими или последующими, особенно если данные упорядочены (например, хронологически). Для этого используются функции
LAG(), которая извлекает значения из предыдущих строк, и
LEAD(), которая извлекает значения из последующих строк. В
примере 4 на картинке ниже мы получаем значение суммы из предыдущего месяца с помощью функции
LAG(sales,1). В функцию, помимо названия столбца, передаётся целое число, означающее количество строк, которые нужно отсчитать от текущей (в нашем случае 1). Для первой строки, очевидно, нет предыдущего значения, поэтому функция возвращает
NULL.
Источник: https://app.pluralsight.com/library/courses/combining-filtering-data-postgresql