Стандартные оконные функции
| Возможность | Поддерживается? |
|---|---|
произвольная спецификация окна (count(*) over (partition by id order by time desc)) | ✅ |
выражения с оконными функциями, например (count(*) over ()) / 2) | ✅ |
предложение WINDOW (select ... from table window w as (partition by id)) | ✅ |
рамка окна ROWS | ✅ |
рамка окна RANGE | ✅ (по умолчанию) |
синтаксис INTERVAL для рамки окна DateTime RANGE OFFSET | ❌ (вместо этого укажите количество секунд (RANGE работает с любым числовым типом).) |
рамка окна GROUPS | ❌ |
вычисление агрегатных функций по рамке окна (sum(value) over (order by time)) | ✅ (Поддерживаются все агрегатные функции) |
rank(), dense_rank(), row_number() | ✅ Псевдоним: denseRank() |
percent_rank() | ✅ Эффективно вычисляет относительную позицию значения в пределах партиции в наборе данных. Эта функция фактически заменяет более многословное и вычислительно затратное ручное SQL-вычисление, записываемое как ifNull((rank() OVER(PARTITION BY x ORDER BY y) - 1) / nullif(count(1) OVER(PARTITION BY x) - 1, 0), 0) Псевдоним: percentRank() |
cume_dist() | ✅ Вычисляет кумулятивное распределение значения в группе значений. Возвращает процент строк со значениями, меньшими или равными значению в текущей строке. |
lag/lead(value, offset) | ✅ Также можно использовать одно из следующих обходных решений: 1) any(value) over (.... rows between <offset> preceding and <offset> preceding), или following для 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). |
Оконные функции, специфичные для ClickHouse
Также доступна следующая оконная функция, специфичная для ClickHouse:nonNegativeDerivative(metric_column, timestamp_column[, INTERVAL X UNITS])
Вычисляет неотрицательную производную для заданногоmetric_column по timestamp_column.
INTERVAL можно опустить; значение по умолчанию — INTERVAL 1 SECOND.
Вычисляемое значение для каждой строки:
0для первой строки,- для -й строки.
Синтаксис
PARTITION BY- определяет, как разбить результирующий набор на группы.ORDER BY- определяет порядок строк внутри группы при вычислении aggregate_function.ROWS or RANGE- определяет границы рамки окна, в пределах которой вычисляется aggregate_function.WINDOW- позволяет нескольким выражениям использовать одно и то же определение окна.
Функции
row_number()- Нумерует текущую строку в пределах её партиции, начиная с 1.first_value(x)- Возвращает первое значение, вычисленное в пределах упорядоченной рамки окна.last_value(x)- Возвращает последнее значение, вычисленное в пределах упорядоченной рамки окна.nth_value(x, offset)- Возвращает первое значение, отличное от NULL, вычисленное для n-й строки (offset) в пределах упорядоченной рамки окна.rank()- Присваивает текущей строке ранг в пределах её партиции с пропусками.dense_rank()- Присваивает текущей строке ранг в пределах её партиции без пропусков.lagInFrame(x)- Возвращает значение, вычисленное для строки, находящейся на указанное физическое смещение перед текущей строкой в пределах упорядоченной рамки окна.leadInFrame(x)- Возвращает значение, вычисленное для строки, находящейся на указанное смещение после текущей строки в пределах упорядоченной рамки окна.
Примеры
Нумерация строк
Функции агрегации
Партиционирование по столбцу
Границы рамки окна
Примеры из практики
Максимальная/общая зарплата по отделам
Нарастающий итог
Скользящее среднее (по 3 строкам)
Скользящее среднее (за 10 секунд)
Скользящее среднее (за 10 дней)
Range и ORDER BY toDate(ts) мы формируем рамку окна размером 10 единиц, и благодаря toDate(ts) такой единицей является день.