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

Содержание

Устройство

  • Обработка набора строк
    • Связанных с текущей
    • Без группировки
  • Описываются в заголовке select
    • Применяются после where/group by/having
  • Синтаксис
    • function([distinct] {Столбцы | *}) over (Окно) as Имя
      

Пример: успеваемость в группе

  • Запрос
    select
        StudentId, StudentName, StudentGroup, AvgPoints,
        rank() over 
            (partition by StudentGroup order by AvgPoints desc)
            as Rank
    from StudentInfo order by StudentGroup, StudentName;
    
  • Результат
    Id Name Group Points Rank
    5 Смирнов С.С. M3438 90 1
    1 Иванов И.И. M3439 80 4
    4 Михайлов М.М M3439 90 2
    2 Петров П.П. M3439 100 1
    3 Сидоров С.С. M3439 90 2

Разбиение на корзины

  • Синтаксис
    • partition by Столбцы
      
    • По-умолчанию: одна корзина
  • Пример
    • rank() over (order by AvgPoints desc) as Rank
      
    • Результат
      Id Name Group Points Rank
      5 Смирнов С.С. M3438 90 2
      1 Иванов И.И. M3439 80 5
      4 Михайлов М.М M3439 90 2
      2 Петров П.П. M3439 100 1
      3 Сидоров С.С. M3439 90 2

Порядок в корзине

  • Синтаксис
    • order by Столбцы
      
    • Столбец [{asc | desc}] [nulls {first | last}]
      
    • По-умолчанию: все равны
  • Пример
    • rank() over (partition by StudentGroup) as Rank
      
    • Результат
      Id Name Group Points Rank
      5 Смирнов С.С. M3438 90 1
      1 Иванов И.И. M3439 80 1
      4 Михайлов М.М M3439 90 1
      2 Петров П.П. M3439 100 1
      3 Сидоров С.С. M3439 90 1

Агрегирующие функции

Содержание

Агрегирующие функции

  • Функции
    • Количество (count)
    • Сумма/среднее (sum/avg)
    • Минимум/максимум (min/max)
  • Пример
    • max(AvgPoints) over (partition by StudentGroup) as M
      
    • Результат
      Id Name Group Points Max
      5 Смирнов С.С. M3438 90 90
      1 Иванов И.И. M3439 80 360
      4 Михайлов М.М M3439 90 280
      2 Петров П.П. M3439 100 100
      3 Сидоров С.С. M3439 90 280

Нарастающие итоги

  • Пример
    • sum(AvgPoints) over 
      (partition by StudentGroup order by AvgPoints desc)
      as Sum
      
    • Результат
      Id Name Group Points S
      5 Смирнов С.С. M3438 90 5
      1 Иванов И.И. M3439 80 8
      4 Михайлов М.М M3439 90 7
      2 Петров П.П. M3439 100
      3 Сидоров С.С. M3439 90 7

Отбор строк

  • Синтаксис
    filter (where Условие)
    
  • Пример
    • sum(StudentId) filter (where AvgPoints < 100) over 
      (partition by StudentGroup order by AvgPoints desc)
      as Sum
      
    • Результат
      Id Name Group Points S
      5 Смирнов С.С. M3438 90 5
      1 Иванов И.И. M3439 80 8
      4 Михайлов М.М M3439 90 7
      2 Петров П.П. M3439 100
      3 Сидоров С.С. M3439 90 7

Порядковые функции

Содержание

Уникальный номер строки

  • Функция row_number()
  • Пример 4
    • row_number() over 
      (partition by StudentGroup order by AvgPoints desc)
      as Row
      
    • Результат
      Id Name Group Points Row
      5 Смирнов С.С. M3438 90 1
      1 Иванов И.И. M3439 80 4
      4 Михайлов М.М M3439 90 3
      2 Петров П.П. M3439 100 1
      3 Сидоров С.С. M3439 90 2

Ранг с пропусками

  • Функция rank()
  • Пример
    • rank() over 
      (partition by StudentGroup order by AvgPoints desc)
      as Rank
      
    • Результат
      Id Name Group Points Rank
      5 Смирнов С.С. M3438 90 1
      1 Иванов И.И. M3439 80 4
      4 Михайлов М.М M3439 90 2
      2 Петров П.П. M3439 100 1
      3 Сидоров С.С. M3439 90 2

Ранг без пропусков

  • Функция dense_rank()
  • Пример
    • dense_rank() over 
      (partition by StudentGroup order by AvgPoints desc)
      as Rank
      
    • Результат
      Id Name Group Points Rank
      5 Смирнов С.С. M3438 90 1
      1 Иванов И.И. M3439 80 3
      4 Михайлов М.М M3439 90 2
      2 Петров П.П. M3439 100 1
      3 Сидоров С.С. M3439 90 2

Относительное положение

  • Функция percent_rank()
    • (rank() - 1) / (count() - 1)
  • Пример
    • percent_rank() over 
      (partition by StudentGroup order by AvgPoints desc)
      as Rank
      
    • Результат
      Id Name Group Points Rank
      5 Смирнов С.С. M3438 90 0
      1 Иванов И.И. M3439 80 1
      4 Михайлов М.М M3439 90 0.33
      2 Петров П.П. M3439 100 0
      3 Сидоров С.С. M3439 90 0.33

«Кумулятивное распределение»

  • Функция cume_dist()
    • (число-предшествующих-либо-равных) / count()
      
  • Пример
    • cume_dist() over 
      (partition by StudentGroup order by AvgPoints desc)
      as Rank
      
    • Результат
      Id Name Group Points Rank
      5 Смирнов С.С. M3438 90 1
      1 Иванов И.И. M3439 80 1
      4 Михайлов М.М M3439 90 0.75
      2 Петров П.П. M3439 100 0.25
      3 Сидоров С.С. M3439 90 0.75

Разбиение на подкорзины

  • Функция ntile(число-корзин)
  • Пример
    • ntile(2) over 
      (partition by StudentGroup order by AvgPoints desc)
      as Tile
      
    • Результат
      Id Name Group Points Tile
      5 Смирнов С.С. M3438 90 1
      1 Иванов И.И. M3439 80 2
      4 Михайлов М.М M3439 90 2
      2 Петров П.П. M3439 100 1
      3 Сидоров С.С. M3439 90 1

Сдвиги вперёд/назад

  • Функции lag(...) / lead(...)
    • столбец [, сдвиг [, значение ]]
      
  • Пример
    • lag(StudentId, 1, 0) over 
      (partition by StudentGroup order by AvgPoints desc)
      as Lag
      
    • Результат
      Id Name Group Points Lag
      5 Смирнов С.С. M3438 90 0
      1 Иванов И.И. M3439 80 4
      4 Михайлов М.М M3439 90 3
      2 Петров П.П. M3439 100 0
      3 Сидоров С.С. M3439 90 2

Определение фрейма

  • Набор строк относительно данной
  • Синтаксис
    • Режим Начало Исключения
      
    • Режим between Начало and Конец Исключения
      
  • Режимы
    • rows — строки
    • groups — подгруппы равных
    • range — отличающиеся на

Начала и концы

  • Начала и концы
    • Предшествующие
      {unbounded | Сдвиг} preceding
      
    • Равные
      current row
      
    • Последующие
      {unbounded | Сдвиг} following
      

Исключение строк

  • Синтаксис
    exclude {current row | group | ties | no others}
    
  • Значения
    • current row – текущая строка
    • group – равные строки
    • ties – равные строки, текущая остаётся
    • no others – без исключений

Первое значение в фрейме

  • Функции first_value(выражение)
  • Пример
    • first_value(StudentId) over 
          (partition by StudentGroup order by AvgPoints desc 
              groups 1 preceding)
      as Value
      
    • Результат
      Id Name Group Points Value
      5 Смирнов С.С. M3438 90 5
      1 Иванов И.И. M3439 80 3
      4 Михайлов М.М M3439 90 2
      2 Петров П.П. M3439 100 2
      3 Сидоров С.С. M3439 90 2

Последнее значение в фрейме

  • Функции last_value(выражение)
  • Пример
    • last_value(StudentId) over 
          (partition by StudentGroup order by AvgPoints desc 
              rows between current row and 1 following)
      as Value
      
    • Результат
      Id Name Group Points Value
      5 Смирнов С.С. M3438 90 5
      1 Иванов И.И. M3439 80 1
      4 Михайлов М.М M3439 90 1
      2 Петров П.П. M3439 100 3
      3 Сидоров С.С. M3439 90 4

Значение по порядку

  • Функция nth_value(выражение, n)
  • Пример
    • nth_value(StudentId, 2)
      over (partition by StudentGroup order by AvgPoints desc)
      as Value
      
    • Результат
      Id Name Group Points Value
      5 Смирнов С.С. M3438 90
      1 Иванов И.И. M3439 80 3
      4 Михайлов М.М M3439 90 3
      2 Петров П.П. M3439 100
      3 Сидоров С.С. M3439 90 3

Агрегирующие функции

  • Считаются на фрейме

Нарастающие итоги

  • Пример
    • sum(AvgPoints) over 
      (partition by StudentGroup order by AvgPoints desc
          groups between 1 preceding and 1 following except group)
      as Sum
      
    • Результат
      Id Name Group Points S
      5 Смирнов С.С. M3438 90 90
      1 Иванов И.И. M3439 80 260
      4 Михайлов М.М M3439 90 270
      2 Петров П.П. M3439 100 280
      3 Сидоров С.С. M3439 90 270

Группировки

Содержание

Пример: Компания

  • Отделы
    • Команды
      • Сотрудники
  • Клиенты
    • Проекты
  • Периоды
    • Годы
      • Кварталы
  • Платежи
    • Сотрудник × Проект × Квартал

Сотрудники

  • Таблицы
    • Отделы: Departments(DId, D)
    • Команды: Teams(TId, T, DId)
    • Сотрудники: Employees (EId, E, TId)
  • Представление
    • Emp = Departments ⋈ Teams ⋈ Employees
      E T D EId TId DId
      Анна BD Dev 111 11 1
      Вася BD Dev 112 11 1
      Пётр FD Dev 121 12 1
      Иван QA QA 211 21 2
      Яна QA QA 212 21 2

Проекты

  • Таблицы
    • Клиенты: Customers(CId, C)
    • Проекты: Projects(PId, P, CId)
  • Представление
    • Proj = Customers ⋈ Teams
      P C PId Id
      A1 A 11 1
      A2 A 12 1
      B1 B 21 2

Заработки (1)

  • Таблица Payments(EId, PID, Y, Q, A)
  • Представление
    • Pay = Emp ⋈ Proj ⋈ Payments
      E T D P C Y Q A EId TId DId PId CId
      Анна BD Dev A1 A 1 3 1 111 11 1 11 1
      Анна BD Dev A1 A 1 4 2 111 11 1 11 1
      Анна BD Dev A1 A 2 1 3 111 11 1 11 1
      Вася BD Dev A1 A 1 4 10 112 11 1 11 1
      Вася BD Dev A2 A 1 3 20 112 11 1 12 1
      Вася BD Dev B1 B 2 1 30 112 11 1 21 2
      Пётр FD Dev A1 A 1 4 100 121 12 1 11 1
      Пётр FD Dev B1 B 1 3 200 121 12 1 21 2
      Иван QA QA A1 A 2 1 1000 211 21 2 11 1
      Иван QA QA B1 B 1 4 2000 211 21 2 21 2
      Яна QA QA A1 A 2 1 10000 212 21 2 11 1
      Яна QA QA A2 A 1 4 20000 212 21 2 12 1

Заработки (2)

E T A1 A2 A3
Q13 Q14 Q21 Q13 Q14 Q21 Q13 Q14 Q21
Анна BD 1 2 3
Вася BD 10 20 30
Пётр FD 100 200
Иван QA 1000 2000
Яна QA 10000 20000

Заработки работников

  • Запрос
    select E, sum(A) as A from Pay
    group by E, EId
    order by EId;
    
  • Результат
    E A
    Анна 6
    Вася 60
    Пётр 300
    Иван 3000
    Яна 30000

Заработки команд

  • Запрос
    select T, sum(A) as A from Pay
    group by T, TId
    order by TId;
    
  • Результат
    T A
    BD 66
    FD 300
    QA 33000

Множественные гуппировки

  • Подсчет статистики по нескольким группам
    • По каждой в отдельности
    • Исключенные столбцы – null
  • Синтаксис
    • group by grouping sets (Группы)
      
    • Группа
      • (Столбцы)
        
      • Столбец
        

Заработки подразделений

  • Запрос
    select T, D, sum(A) as A from Pay
    group by grouping sets ((T, TId), (D, DId), ())
    order by TId, DId;
    
  • Результат
    T D A
    BD 66
    FD 300
    QA 33000
    Dev 366
    QA 33000
    33366

Группировки на префиксах

  • Подсчет статистики на всех префиксах столбцов
  • Синтаксис
    • group by rollup (С1, С2, С3, ...)
      
  • Эквивалентно
    • group by grouping sets (
          (), 
          С1, 
          (С1, С2), 
          (С1, С2, С3), 
          ...
      )
      

Заработки подразделений

  • Запрос
    select T, D, sum(A) as A from Pay
    group by rollup ((D, DId), (T, TId))
    order by TId, DId;
    
  • Результат
    T D A
    BD 66
    FD 300
    QA 33000
    Dev 366
    QA 33000
    33366

Группировки на подмножествах

  • Подсчет статистики на всех подножествах
  • Синтаксис
    • group by cube (С1, С2, С3, ...)
      
  • Эквивалентно
    • group by grouping sets (
          (),
          С1, С2, С3,
          (С1, С2), (С1, С2), (С2, С3),
          (С1, С2, С3),
          ...
      )
      

Заработки

  • Запрос
    select D, C, Y, Q, sum(A) as A from Pay
    group by cube (
        (D, DId),
        (C, CId),
        (Y, Q)
    )
    order by DId, CId, Y, Q;
    

Результат

D C Y Q A D C Y Q A D C Y Q A
Dev A 1 3 21 QA A 1 4 20000 A 31136
Dev A 1 4 112 QA A 2 1 11000 B 1 3 200
Dev A 2 1 3 QA A 31000 B 1 4 2000
Dev A 136 QA B 1 4 2000 B 2 1 30
Dev B 1 3 200 QA B 2000 B 2230
Dev B 2 1 30 QA 1 4 22000 1 3 221
Dev B 230 QA 2 1 11000 1 4 22112
Dev 1 3 221 QA 33000 2 1 11033
Dev 1 4 112 A 1 3 21 33366
Dev 2 1 33 A 1 4 20112
Dev 366 A 2 1 11003

Литература

Содержание

Дополнительная литература (1)

Дополнительная литература (2)