Стандартные оконные функции
| Возможность | Поддерживается? | Комментарий |
|---|---|---|
Спецификация окна ad hoc (count(*) OVER (PARTITION BY id ORDER BY time DESC)) | ✅ | |
Выражения с оконными функциями, например (count(*) OVER ()) / 2 | ✅ | |
Предложение WINDOW (SELECT ... FROM table WINDOW w AS (PARTITION BY id)) | ✅ | |
Рамка окна ROWS | ✅ | |
Рамка окна RANGE | ✅ | Используется по умолчанию, если рамка окна явно не указана (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW). |
Синтаксис INTERVAL для рамки DateTime RANGE OFFSET | ❌ | Вместо этого укажите количество секунд (RANGE работает с любым числовым типом). |
Рамка окна GROUPS | ❌ | |
Вычисление агрегатных функций по рамке окна (sum(value) OVER (ORDER BY time)) | ✅ | Поддерживаются все агрегатные функции. |
rank(), dense_rank()/denseRank(), row_number() | ✅ | |
percent_rank()/percentRank() | ✅ | Эффективно вычисляет относительное положение значения в пределах партиции. Заменяет более многословный и вычислительно затратный ручной SQL-расчёт: ifNull((rank() OVER (PARTITION BY x ORDER BY y) - 1) / nullif(count(1) OVER (PARTITION BY x) - 1, 0), 0). |
cume_dist() | ✅ | Вычисляет кумулятивное распределение значения в группе значений. Возвращает процент строк со значениями, меньшими или равными значению в текущей строке. |
lag/lead(value, offset) | ✅ | Также можно использовать один из следующих обходных вариантов: 1) any(value) OVER (... ROWS BETWEEN <offset> PRECEDING AND <offset> PRECEDING) или FOLLOWING вместо PRECEDING для lead 2) lagInFrame/leadInFrame — это аналогичные функции, но они учитывают рамку окна. Чтобы получить поведение, идентичное lag/lead, используйте ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING. |
ntile(buckets) | ✅ | Укажите окно, например: (PARTITION BY x ORDER BY y ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING). |
Синтаксис
PARTITION BY- определяет, как разбить результирующий набор на группы.ORDER BY- определяет порядок строк внутри группы при вычислении aggregate_function.ROWS or RANGE- определяет границы рамки окна, в пределах которой вычисляется aggregate_function.WINDOW- позволяет нескольким выражениям использовать одно и то же определение окна.
Функции, доступные только как оконные функции
lagInFrame, leadInFrame и nonNegativeDerivative — расширения ClickHouse.
| Function | Description |
|---|---|
row_number() | Пронумеровать текущую строку в пределах её партиции, начиная с 1. |
first_value(x) | Вернуть первое значение, вычисленное в пределах упорядоченной рамки окна. |
last_value(x) | Вернуть последнее значение, вычисленное в пределах упорядоченной рамки окна. |
nth_value(x, offset) | Вернуть первое значение, отличное от NULL, вычисленное для n-й строки (offset) в пределах упорядоченной рамки окна. |
rank() | Присвоить ранг текущей строке в пределах её партиции с пропусками. |
dense_rank() | Присвоить ранг текущей строке в пределах её партиции без пропусков. |
lagInFrame(x) | Вернуть значение, вычисленное для строки, находящейся на заданное физическое смещение перед текущей строкой в пределах упорядоченной рамки окна. |
leadInFrame(x) | Вернуть значение, вычисленное для строки, находящейся на заданное число строк после текущей строки в пределах упорядоченной рамки окна. |
nonNegativeDerivative(metric_column, timestamp_column[, INTERVAL X UNITS]) | Вычислить неотрицательную производную metric_column по timestamp_column. Специфична для ClickHouse. |
Примеры
Нумерация строк
Функции агрегации
Партиционирование по столбцу
Границы рамки окна
Примеры из практики
Максимальная/общая зарплата по отделам
Нарастающий итог
Скользящее среднее (по 3 строкам)
Скользящее среднее (за 10 секунд)
Скользящее среднее (за 10 дней)
Range и ORDER BY toDate(ts) мы формируем рамку окна размером 10 единиц, и благодаря toDate(ts) этой единицей является день.