2020-10-26 10:29:30 +00:00
---
2022-04-09 13:29:05 +00:00
sidebar_position: 38
sidebar_label: "Параметрические агрегатные функции"
2020-10-26 10:29:30 +00:00
---
2020-03-22 09:14:59 +00:00
# Параметрические агрегатные функции {#aggregate_functions_parametric}
2017-10-25 05:27:09 +00:00
Некоторые агрегатные функции могут принимать не только столбцы-аргументы (по которым производится свёртка), но и набор параметров - констант для инициализации. Синтаксис - две пары круглых скобок вместо одной. Первая - для параметров, вторая - для аргументов.
2020-03-20 18:20:59 +00:00
## histogram {#histogram}
2019-09-23 23:59:49 +00:00
Рассчитывает адаптивную гистограмму. Н е гарантирует точного результата.
2021-03-13 18:18:45 +00:00
``` sql
histogram(number_of_bins)(values)
```
2020-03-20 18:20:59 +00:00
2019-09-23 23:59:49 +00:00
Функция использует [A Streaming Parallel Decision Tree Algorithm ](http://jmlr.org/papers/volume11/ben-haim10a/ben-haim10a.pdf ). Границы столбцов устанавливаются по мере поступления новых данных в функцию. В общем случае столбцы имею разную ширину.
2021-03-13 18:18:45 +00:00
**Аргументы**
`values` — [выражение ](../syntax.md#syntax-expressions ), предоставляющее входные значения.
2019-09-23 23:59:49 +00:00
**Параметры**
`number_of_bins` — максимальное количество корзин в гистограмме. Функция автоматически вычисляет количество корзин. Она пытается получить указанное количество корзин, но если не получилось, то в результате корзин будет меньше.
**Возвращаемые значения**
2020-04-30 18:19:18 +00:00
- [Массив ](../../sql-reference/data-types/array.md ) [кортежей ](../../sql-reference/data-types/tuple.md ) следующего вида:
2019-09-23 23:59:49 +00:00
2020-03-21 04:11:51 +00:00
```
[(lower_1, upper_1, height_1), ... (lower_N, upper_N, height_N)]
```
2019-09-23 23:59:49 +00:00
2020-03-21 04:11:51 +00:00
- `lower` — нижняя граница корзины.
- `upper` — верхняя граница корзины.
- `height` — количество значений в корзине.
2019-09-23 23:59:49 +00:00
**Пример**
2020-03-20 18:20:59 +00:00
``` sql
SELECT histogram(5)(number + 1)
2019-09-23 23:59:49 +00:00
FROM (
2020-03-20 18:20:59 +00:00
SELECT *
FROM system.numbers
2019-09-23 23:59:49 +00:00
LIMIT 20
)
```
2020-03-20 18:20:59 +00:00
``` text
2019-09-23 23:59:49 +00:00
┌─histogram(5)(plus(number, 1))───────────────────────────────────────────┐
│ [(1,4.5,4),(4.5,8.5,4),(8.5,12.75,4.125),(12.75,17,4.625),(17,20,3.25)] │
└─────────────────────────────────────────────────────────────────────────┘
```
2020-04-30 18:19:18 +00:00
С помощью функции [bar ](../../sql-reference/aggregate-functions/parametric-functions.md#function-bar ) можно визуализировать гистограмму, например:
2019-09-23 23:59:49 +00:00
2020-03-20 18:20:59 +00:00
``` sql
2019-09-23 23:59:49 +00:00
WITH histogram(5)(rand() % 100) AS hist
2020-03-20 18:20:59 +00:00
SELECT
arrayJoin(hist).3 AS height,
2019-09-23 23:59:49 +00:00
bar(height, 0, 6, 5) AS bar
2020-03-20 18:20:59 +00:00
FROM
2019-09-23 23:59:49 +00:00
(
SELECT *
FROM system.numbers
LIMIT 20
)
```
2020-03-20 18:20:59 +00:00
``` text
2019-09-23 23:59:49 +00:00
┌─height─┬─bar───┐
│ 2.125 │ █▋ │
│ 3.25 │ ██▌ │
│ 5.625 │ ████▏ │
│ 5.625 │ ████▏ │
│ 3.375 │ ██▌ │
└────────┴───────┘
```
В этом случае необходимо помнить, что границы корзин гистограммы не известны.
2020-03-20 18:20:59 +00:00
## sequenceMatch(pattern)(timestamp, cond1, cond2, …) {#function-sequencematch}
2017-10-25 05:27:09 +00:00
2019-11-03 16:39:08 +00:00
Проверяет, содержит ли последовательность событий цепочку, которая соответствует указанному шаблону.
2017-10-25 05:27:09 +00:00
2020-03-20 18:20:59 +00:00
``` sql
2019-10-17 13:47:19 +00:00
sequenceMatch(pattern)(timestamp, cond1, cond2, ...)
```
2022-04-09 13:29:05 +00:00
:::danger "Предупреждение"
2019-10-17 13:47:19 +00:00
События, произошедшие в одну и ту же секунду, располагаются в последовательности в неопределенном порядке, что может повлиять на результат работы функции.
2021-03-13 18:18:45 +00:00
**Аргументы**
2019-10-17 13:47:19 +00:00
2020-04-30 18:19:18 +00:00
- `timestamp` — столбец, содержащий метки времени. Типичный тип данных столбца — `Date` или `DateTime` . Также можно использовать любой из поддержанных типов данных [UInt ](../../sql-reference/aggregate-functions/parametric-functions.md ).
2019-10-17 13:47:19 +00:00
2020-03-21 04:11:51 +00:00
- `cond1` , `cond2` — условия, описывающие цепочку событий. Тип данных — `UInt8` . Можно использовать до 32 условий. Функция учитывает только те события, которые указаны в условиях. Функция пропускает данные из последовательности, если они не описаны ни в одном из условий.
2019-10-17 13:47:19 +00:00
2021-03-13 18:18:45 +00:00
**Параметры**
- `pattern` — строка с шаблоном. Смотрите [Синтаксис шаблонов ](#sequence-function-pattern-syntax ).
2019-10-17 13:47:19 +00:00
**Возвращаемые значения**
2020-03-21 04:11:51 +00:00
- 1, если цепочка событий, соответствующая шаблону найдена.
- 0, если цепочка событий, соответствующая шаблону не найдена.
2019-10-17 13:47:19 +00:00
Тип: `UInt8` .
< a name = "sequence-function-pattern-syntax" > < / a >
**Синтаксис шаблонов**
2020-03-21 04:11:51 +00:00
- `(?N)` — соответствует условию на позиции `N` . Условия пронумерованы по порядку в диапазоне `[1, 32]` . Например, `(?1)` соответствует условию, заданному параметром `cond1` .
2019-10-17 13:47:19 +00:00
2020-03-21 04:11:51 +00:00
- `.*` — соответствует любому количеству событий. Для этого элемента шаблона не надо задавать условия.
2019-10-17 13:47:19 +00:00
2021-06-15 16:58:20 +00:00
- `(?t operator value)` — устанавливает время в секундах, которое должно разделять два события. Например, шаблон `(?1)(?t>1800)(?2)` соответствует событиям, которые произошли более чем через 1800 секунд друг от друга. Между этими событиями может находиться произвольное количество любых событий. Операторы могут быть `>=` , `>` , `<` , `<=` , `==` .
2019-10-17 13:47:19 +00:00
**Примеры**
Пусть таблица `t` содержит следующие данные:
2020-03-20 18:20:59 +00:00
``` text
2019-10-17 13:47:19 +00:00
┌─time─┬─number─┐
│ 1 │ 1 │
│ 2 │ 3 │
│ 3 │ 2 │
└──────┴────────┘
```
Выполним запрос:
2020-03-20 18:20:59 +00:00
``` sql
2019-10-17 13:47:19 +00:00
SELECT sequenceMatch('(?1)(?2)')(time, number = 1, number = 2) FROM t
```
2020-03-20 18:20:59 +00:00
``` text
2019-10-17 13:47:19 +00:00
┌─sequenceMatch('(?1)(?2)')(time, equals(number, 1), equals(number, 2))─┐
│ 1 │
└───────────────────────────────────────────────────────────────────────┘
```
2019-11-03 16:39:39 +00:00
Функция нашла цепочку событий, в которой число 2 следует за числом 1. Число 3 между ними было пропущено, поскольку оно не было использовано ни в одном из условий.
2019-10-17 13:47:19 +00:00
2020-03-20 18:20:59 +00:00
``` sql
2019-10-17 13:47:19 +00:00
SELECT sequenceMatch('(?1)(?2)')(time, number = 1, number = 2, number = 3) FROM t
```
2020-03-20 18:20:59 +00:00
``` text
2019-10-17 13:47:19 +00:00
┌─sequenceMatch('(?1)(?2)')(time, equals(number, 1), equals(number, 2), equals(number, 3))─┐
│ 0 │
└──────────────────────────────────────────────────────────────────────────────────────────┘
```
В этом случае функция не может найти цепочку событий, соответствующую шаблону, поскольку событие для числа 3 произошло между 1 и 2. Если бы в этом же случае мы бы проверяли условие на событие для числа 4, то цепочка бы соответствовала шаблону.
2020-03-20 18:20:59 +00:00
``` sql
2019-10-17 13:47:19 +00:00
SELECT sequenceMatch('(?1)(?2)')(time, number = 1, number = 2, number = 4) FROM t
```
2020-03-20 18:20:59 +00:00
``` text
2019-10-17 13:47:19 +00:00
┌─sequenceMatch('(?1)(?2)')(time, equals(number, 1), equals(number, 2), equals(number, 4))─┐
│ 1 │
└──────────────────────────────────────────────────────────────────────────────────────────┘
```
2017-10-25 05:27:09 +00:00
2019-10-17 13:47:19 +00:00
**Смотрите также**
2017-10-25 05:27:09 +00:00
2020-03-21 04:11:51 +00:00
- [sequenceCount ](#function-sequencecount )
2017-10-25 05:27:09 +00:00
2020-03-20 18:20:59 +00:00
## sequenceCount(pattern)(time, cond1, cond2, …) {#function-sequencecount}
2017-10-25 05:27:09 +00:00
2021-08-16 12:06:44 +00:00
Вычисляет количество цепочек событий, соответствующих шаблону. Функция обнаруживает только непересекающиеся цепочки событий. Она начинает искать следующую цепочку только после того, как полностью совпала текущая цепочка событий.
2019-10-17 13:47:19 +00:00
2022-04-09 13:29:05 +00:00
:::danger "Предупреждение"
2019-10-17 13:47:19 +00:00
События, произошедшие в одну и ту же секунду, располагаются в последовательности в неопределенном порядке, что может повлиять на результат работы функции.
2017-10-25 05:27:09 +00:00
2020-03-20 18:20:59 +00:00
``` sql
2019-10-17 13:47:19 +00:00
sequenceCount(pattern)(timestamp, cond1, cond2, ...)
2017-10-25 05:27:09 +00:00
```
2021-03-13 18:18:45 +00:00
**Аргументы**
2017-10-25 05:27:09 +00:00
2020-04-30 18:19:18 +00:00
- `timestamp` — столбец, содержащий метки времени. Типичный тип данных столбца — `Date` или `DateTime` . Также можно использовать любой из поддержанных типов данных [UInt ](../../sql-reference/aggregate-functions/parametric-functions.md ).
2017-10-25 05:27:09 +00:00
2020-03-21 04:11:51 +00:00
- `cond1` , `cond2` — условия, описывающие цепочку событий. Тип данных — `UInt8` . Можно использовать до 32 условий. Функция учитывает только те события, которые указаны в условиях. Функция пропускает данные из последовательности, если они не описаны ни в одном из условий.
2017-10-25 05:27:09 +00:00
2021-03-13 18:18:45 +00:00
**Параметры**
- `pattern` — строка с шаблоном. Смотрите [Синтаксис шаблонов ](#sequence-function-pattern-syntax ).
2019-10-17 13:47:19 +00:00
**Возвращаемое значение**
2017-10-25 05:27:09 +00:00
2020-03-21 04:11:51 +00:00
- Число непересекающихся цепочек событий, соответствущих шаблону.
2017-10-25 05:27:09 +00:00
2019-10-17 13:47:19 +00:00
Тип: `UInt64` .
2017-10-25 05:27:09 +00:00
2019-10-17 13:47:19 +00:00
**Пример**
2017-10-25 05:27:09 +00:00
2019-10-17 13:47:19 +00:00
Пусть таблица `t` содержит следующие данные:
2020-03-20 18:20:59 +00:00
``` text
2019-10-17 13:47:19 +00:00
┌─time─┬─number─┐
│ 1 │ 1 │
│ 2 │ 3 │
│ 3 │ 2 │
│ 4 │ 1 │
│ 5 │ 3 │
│ 6 │ 2 │
└──────┴────────┘
```
2017-10-25 05:27:09 +00:00
2019-10-17 13:47:19 +00:00
Вычислим сколько раз число 2 стоит после числа 1, причем между 1 и 2 могут быть любые числа:
2020-03-20 18:20:59 +00:00
``` sql
2019-10-17 13:47:19 +00:00
SELECT sequenceCount('(?1).*(?2)')(time, number = 1, number = 2) FROM t
```
2020-03-20 18:20:59 +00:00
``` text
2019-10-17 13:47:19 +00:00
┌─sequenceCount('(?1).*(?2)')(time, equals(number, 1), equals(number, 2))─┐
│ 2 │
└─────────────────────────────────────────────────────────────────────────┘
```
2017-10-25 05:27:09 +00:00
2019-10-17 13:47:19 +00:00
**Смотрите также**
2017-10-25 05:27:09 +00:00
2020-03-21 04:11:51 +00:00
- [sequenceMatch ](#function-sequencematch )
2017-10-25 05:27:09 +00:00
2019-12-25 20:55:07 +00:00
## windowFunnel {#windowfunnel}
2018-08-01 09:21:12 +00:00
Отыскивает цепочки событий в скользящем окне по времени и вычисляет максимальное количество произошедших событий из цепочки.
2019-12-25 20:55:07 +00:00
Функция работает по алгоритму:
2020-03-21 04:11:51 +00:00
- Функция отыскивает данные, на которых срабатывает первое условие из цепочки, и присваивает счетчику событий значение 1. С этого же момента начинается отсчет времени скользящего окна.
2019-12-25 20:55:07 +00:00
2020-03-21 04:11:51 +00:00
- Если в пределах окна последовательно попадаются события из цепочки, то счетчик увеличивается. Если последовательность событий нарушается, то счетчик не растет.
2019-12-25 20:55:07 +00:00
2020-03-21 04:11:51 +00:00
- Если в данных оказалось несколько цепочек разной степени завершенности, то функция выдаст только размер самой длинной цепочки.
2019-12-25 20:55:07 +00:00
**Синтаксис**
2018-08-01 09:21:12 +00:00
2020-03-20 18:20:59 +00:00
``` sql
2021-03-23 11:44:10 +00:00
windowFunnel(window, [mode, [mode, ... ]])(timestamp, cond1, cond2, ..., condN)
2018-08-01 09:21:12 +00:00
```
2021-03-13 18:18:45 +00:00
**Аргументы**
2018-08-01 09:21:12 +00:00
2020-04-30 18:19:18 +00:00
- `timestamp` — имя столбца, содержащего временные отметки. [Date ](../../sql-reference/aggregate-functions/parametric-functions.md ), [DateTime ](../../sql-reference/aggregate-functions/parametric-functions.md#data_type-datetime ) и другие параметры с типом `Integer` . В случае хранения меток времени в столбцах с типом `UInt64` , максимально допустимое значение соответствует ограничению для типа `Int64` , т.е . равно `2^63-1` .
- `cond` — условия или данные, описывающие цепочку событий. [UInt8 ](../../sql-reference/aggregate-functions/parametric-functions.md ).
2018-08-01 09:21:12 +00:00
2021-03-13 18:18:45 +00:00
**Параметры**
2021-07-29 15:20:55 +00:00
- `window` — ширина скользящего окна по времени. Это время между первым и последним условием. Единица измерения зависит от `timestamp` и может варьироваться. Должно соблюдаться условие `timestamp события cond1 <= timestamp события cond2 <= ... <= timestamp события condN <= timestamp события cond1 + window` .
2021-03-23 11:44:10 +00:00
- `mode` — необязательный параметр. Может быть установленно несколько значений одновременно.
- `'strict'` — не учитывать подряд идущие повторяющиеся события.
- `'strict_order'` — запрещает посторонние события в искомой последовательности. Например, при поиске цепочки `A->B->C` в `A->B->D->C` поиск будет остановлен на `D` и функция вернет 2.
- `'strict_increase'` — условия прменяются только для событий с о строго возрастающими временными метками.
2021-03-13 18:18:45 +00:00
2018-08-01 09:21:12 +00:00
**Возвращаемое значение**
2019-12-25 20:55:07 +00:00
Максимальное количество последовательно сработавших условий из цепочки в пределах скользящего окна по времени. Исследуются все цепочки в выборке.
Тип: `Integer` .
2018-08-01 09:21:12 +00:00
**Пример**
2019-12-25 20:55:07 +00:00
Определим, успевает ли пользователь за установленный период выбрать телефон в интернет-магазине, купить е г о и сделать повторный заказ.
2018-08-01 09:21:12 +00:00
Зададим следующую цепочку событий:
2020-03-20 18:20:59 +00:00
1. Пользователь вошел в личный кабинет (`eventID = 1001`).
2. Пользователь ищет телефон (`eventID = 1003, product = 'phone'`).
3. Пользователь сделал заказ (`eventID = 1009`)
4. Пользователь сделал повторный заказ (`eventID = 1010`).
2019-12-25 20:55:07 +00:00
Входная таблица:
2018-08-01 09:21:12 +00:00
2020-03-20 18:20:59 +00:00
``` text
2019-12-25 20:55:07 +00:00
┌─event_date─┬─user_id─┬───────────timestamp─┬─eventID─┬─product─┐
│ 2019-01-28 │ 1 │ 2019-01-29 10:00:00 │ 1003 │ phone │
└────────────┴─────────┴─────────────────────┴─────────┴─────────┘
┌─event_date─┬─user_id─┬───────────timestamp─┬─eventID─┬─product─┐
│ 2019-01-31 │ 1 │ 2019-01-31 09:00:00 │ 1007 │ phone │
└────────────┴─────────┴─────────────────────┴─────────┴─────────┘
┌─event_date─┬─user_id─┬───────────timestamp─┬─eventID─┬─product─┐
│ 2019-01-30 │ 1 │ 2019-01-30 08:00:00 │ 1009 │ phone │
└────────────┴─────────┴─────────────────────┴─────────┴─────────┘
┌─event_date─┬─user_id─┬───────────timestamp─┬─eventID─┬─product─┐
│ 2019-02-01 │ 1 │ 2019-02-01 08:00:00 │ 1010 │ phone │
└────────────┴─────────┴─────────────────────┴─────────┴─────────┘
```
Сделаем запрос и узнаем, как далеко пользователь `user_id` смог пройти по цепочке за период в январе-феврале 2019-г о года.
Запрос:
2018-08-01 09:21:12 +00:00
2020-03-20 18:20:59 +00:00
``` sql
2018-08-01 09:21:12 +00:00
SELECT
level,
count() AS c
FROM
(
SELECT
user_id,
2019-12-25 20:55:07 +00:00
windowFunnel(6048000000000000)(timestamp, eventID = 1003, eventID = 1009, eventID = 1007, eventID = 1010) AS level
FROM trend
WHERE (event_date >= '2019-01-01') AND (event_date < = '2019-02-02')
2018-08-01 09:21:12 +00:00
GROUP BY user_id
)
GROUP BY level
2021-05-04 10:19:45 +00:00
ORDER BY level ASC;
2018-08-01 09:21:12 +00:00
```
2019-12-07 18:20:08 +00:00
## retention {#retention}
2020-03-20 18:20:59 +00:00
Аналитическая функция, которая показывает, насколько
2019-12-07 18:20:08 +00:00
выдерживаются те или иные условия, например, удержание динамики/уровня [посещаемости сайта ](https://yandex.ru/support/partner2/statistics/metrika-visitors-statistics.html?lang=ru ).
2020-05-15 04:34:54 +00:00
Функция принимает набор (от 1 до 32) логических условий, как в [WHERE ](../../sql-reference/statements/select/where.md#select-where ), и применяет их к заданному набору данных.
2019-12-07 18:20:08 +00:00
2021-03-13 18:18:45 +00:00
Условия, кроме первого, применяются попарно: результат второго будет истинным, если истинно первое и второе, третьего - если истинно первое и третье и т.д.
2019-12-07 18:20:08 +00:00
2020-03-20 18:20:59 +00:00
**Синтаксис**
2019-12-07 18:20:08 +00:00
2020-03-20 18:20:59 +00:00
``` sql
2019-12-07 18:20:08 +00:00
retention(cond1, cond2, ..., cond32)
```
2021-03-13 18:18:45 +00:00
**Аргументы**
2019-12-07 18:20:08 +00:00
2020-03-21 04:11:51 +00:00
- `cond` — вычисляемое условие или выражение, которое возвращает `UInt8` результат (1/0).
2019-12-07 18:20:08 +00:00
**Возвращаемое значение**
Массив из 1 или 0.
2020-03-21 04:11:51 +00:00
- 1 — условие выполнено.
- 0 — условие не выполнено.
2019-12-07 18:20:08 +00:00
Тип: `UInt8` .
**Пример**
Рассмотрим пример расчета функции `retention` для определения посещаемости сайта.
2020-03-20 18:20:59 +00:00
**1.** Создадим таблицу для илюстрации примера.
2019-12-07 18:20:08 +00:00
2020-03-20 18:20:59 +00:00
``` sql
2019-12-07 18:20:08 +00:00
CREATE TABLE retention_test(date Date, uid Int32)ENGINE = Memory;
INSERT INTO retention_test SELECT '2020-01-01', number FROM numbers(5);
INSERT INTO retention_test SELECT '2020-01-02', number FROM numbers(10);
INSERT INTO retention_test SELECT '2020-01-03', number FROM numbers(15);
```
Входная таблица:
Запрос:
2020-03-20 18:20:59 +00:00
``` sql
2019-12-07 18:20:08 +00:00
SELECT * FROM retention_test
```
Ответ:
2020-03-20 18:20:59 +00:00
``` text
2019-12-07 18:20:08 +00:00
┌───────date─┬─uid─┐
│ 2020-01-01 │ 0 │
│ 2020-01-01 │ 1 │
│ 2020-01-01 │ 2 │
│ 2020-01-01 │ 3 │
│ 2020-01-01 │ 4 │
└────────────┴─────┘
┌───────date─┬─uid─┐
│ 2020-01-02 │ 0 │
│ 2020-01-02 │ 1 │
│ 2020-01-02 │ 2 │
│ 2020-01-02 │ 3 │
│ 2020-01-02 │ 4 │
│ 2020-01-02 │ 5 │
│ 2020-01-02 │ 6 │
│ 2020-01-02 │ 7 │
│ 2020-01-02 │ 8 │
│ 2020-01-02 │ 9 │
└────────────┴─────┘
┌───────date─┬─uid─┐
│ 2020-01-03 │ 0 │
│ 2020-01-03 │ 1 │
│ 2020-01-03 │ 2 │
│ 2020-01-03 │ 3 │
│ 2020-01-03 │ 4 │
│ 2020-01-03 │ 5 │
│ 2020-01-03 │ 6 │
│ 2020-01-03 │ 7 │
│ 2020-01-03 │ 8 │
│ 2020-01-03 │ 9 │
│ 2020-01-03 │ 10 │
│ 2020-01-03 │ 11 │
│ 2020-01-03 │ 12 │
│ 2020-01-03 │ 13 │
│ 2020-01-03 │ 14 │
└────────────┴─────┘
```
**2.** Сгруппируем пользователей по уникальному идентификатору `uid` с помощью функции `retention` .
Запрос:
2020-03-20 18:20:59 +00:00
``` sql
2019-12-07 18:20:08 +00:00
SELECT
uid,
retention(date = '2020-01-01', date = '2020-01-02', date = '2020-01-03') AS r
FROM retention_test
WHERE date IN ('2020-01-01', '2020-01-02', '2020-01-03')
GROUP BY uid
ORDER BY uid ASC
```
Результат:
2020-03-20 18:20:59 +00:00
``` text
2019-12-07 18:20:08 +00:00
┌─uid─┬─r───────┐
│ 0 │ [1,1,1] │
│ 1 │ [1,1,1] │
│ 2 │ [1,1,1] │
│ 3 │ [1,1,1] │
│ 4 │ [1,1,1] │
│ 5 │ [0,0,0] │
│ 6 │ [0,0,0] │
│ 7 │ [0,0,0] │
│ 8 │ [0,0,0] │
│ 9 │ [0,0,0] │
│ 10 │ [0,0,0] │
│ 11 │ [0,0,0] │
│ 12 │ [0,0,0] │
│ 13 │ [0,0,0] │
│ 14 │ [0,0,0] │
└─────┴─────────┘
```
**3.** Рассчитаем количество посещений сайта за день.
Запрос:
2020-03-20 18:20:59 +00:00
``` sql
2019-12-07 18:20:08 +00:00
SELECT
sum(r[1]) AS r1,
sum(r[2]) AS r2,
sum(r[3]) AS r3
FROM
(
SELECT
uid,
retention(date = '2020-01-01', date = '2020-01-02', date = '2020-01-03') AS r
FROM retention_test
WHERE date IN ('2020-01-01', '2020-01-02', '2020-01-03')
GROUP BY uid
)
```
Результат:
2020-03-20 18:20:59 +00:00
``` text
2019-12-07 18:20:08 +00:00
┌─r1─┬─r2─┬─r3─┐
│ 5 │ 5 │ 5 │
└────┴────┴────┘
```
Где:
2020-03-21 04:11:51 +00:00
- `r1` - количество уникальных посетителей за 2020-01-01 (`cond1`).
- `r2` - количество уникальных посетителей в период между 2020-01-01 и 2020-01-02 (`cond1` и `cond2` ).
- `r3` - количество уникальных посетителей в период между 2020-01-01 и 2020-01-03 (`cond1` и `cond3` ).
2018-08-01 09:21:12 +00:00
2020-03-20 18:20:59 +00:00
## uniqUpTo(N)(x) {#uniquptonx}
2017-10-25 05:27:09 +00:00
Вычисляет количество различных значений аргумента, если оно меньше или равно N.
В случае, если количество различных значений аргумента больше N, возвращает N + 1.
Рекомендуется использовать для маленьких N - до 10. Максимальное значение N - 100.
Для состояния агрегатной функции используется количество оперативки равное 1 + N \* размер одного значения байт.
2019-08-23 10:55:34 +00:00
Для строк запоминается не криптографический хэш, имеющий размер 8 байт. Т о есть, для строк вычисление приближённое.
2017-10-25 05:27:09 +00:00
Функция также работает для нескольких аргументов.
Работает максимально быстро за исключением патологических случаев, когда используется большое значение N и количество уникальных значений чуть меньше N.
Пример применения:
2020-03-20 18:20:59 +00:00
``` text
2017-10-25 05:27:09 +00:00
Задача: показывать в отчёте только поисковые фразы, по которым было хотя бы 5 уникальных посетителей.
Решение: пишем в запросе GROUP BY SearchPhrase HAVING uniqUpTo(4)(UserID) >= 5
```
2018-10-16 10:47:17 +00:00
2021-06-13 13:25:00 +00:00
## sequenceNextNode {#sequenceNextNode}
Возвращает значение следующего события, соответствующего цепочке событий.
_Экс пе р име нта льна я функция, чтобы включить е е , выполните: `SET allow_experimental_funnel_functions = 1` ._
**Синтаксис**
``` sql
sequenceNextNode(direction, base)(timestamp, event_column, base_condition, event1, event2, event3, ...)
```
**Параметры**
- `direction` — используется для навигации по направлениям.
- forward — двигаться вперед.
- backward — двигаться назад.
- `base` — используется для задания начальной точки.
- head — установить начальную точку на первое событие цепочки.
- tail — установить начальную точку на последнее событие цепочки.
2021-06-14 12:39:53 +00:00
- first_match — установить начальную точку на первое соответствующее событие `event1` .
- last_match — установить начальную точку на последнее соответствующее событие `event1` .
2021-07-29 15:27:50 +00:00
2021-06-13 13:25:00 +00:00
**Аргументы**
2021-06-13 13:43:23 +00:00
- `timestamp` — название столбца, содержащего `timestamp` . Поддерживаемые типы данных: [Date ](../../sql-reference/data-types/date.md ), [DateTime ](../../sql-reference/data-types/datetime.md#data_type-datetime ) и другие беззнаковые целые типы.
- `event_column` — название столбца, содержащего значение следующего возвращаемого события. Поддерживаемые типы данных: [String ](../../sql-reference/data-types/string.md ) и [Nullable(String) ](../../sql-reference/data-types/nullable.md ).
2021-06-13 13:25:00 +00:00
- `base_condition` — условие, которому должна соответствовать исходная точка.
2021-06-15 07:27:38 +00:00
- `event1` , `event2` , ... — условия, описывающие цепочку событий. [UInt8 ](../../sql-reference/data-types/int-uint.md ).
2021-06-13 13:25:00 +00:00
**Возвращаемые значения**
2021-06-14 12:39:53 +00:00
- `event_column[next_index]` — если есть совпадение с шаблоном и существует следующее значение.
- `NULL` — если нет совпадений с шаблоном или следующего значения не существует.
2021-06-13 13:25:00 +00:00
Тип: [Nullable(String) ](../../sql-reference/data-types/nullable.md ).
**Пример**
2021-06-14 12:39:53 +00:00
Функцию можно использовать, если есть цепочка событий A->B->C->D->E, и вы хотите определить событие, следующее за B->C, то есть D.
2021-06-13 13:25:00 +00:00
2021-06-15 07:27:38 +00:00
Запрос ищет событие после A->B:
2021-06-13 13:25:00 +00:00
``` sql
CREATE TABLE test_flow (
2021-07-29 15:20:55 +00:00
dt DateTime,
id int,
2021-06-13 13:25:00 +00:00
page String)
2021-07-29 15:20:55 +00:00
ENGINE = MergeTree()
PARTITION BY toYYYYMMDD(dt)
2021-06-13 13:25:00 +00:00
ORDER BY id;
2021-06-14 12:39:53 +00:00
INSERT INTO test_flow VALUES (1, 1, 'A') (2, 1, 'B') (3, 1, 'C') (4, 1, 'D') (5, 1, 'E');
2021-06-13 13:25:00 +00:00
SELECT id, sequenceNextNode('forward', 'head')(dt, page, page = 'A', page = 'A', page = 'B') as next_flow FROM test_flow GROUP BY id;
```
Результат:
``` text
┌─id─┬─next_flow─┐
│ 1 │ C │
└────┴───────────┘
```
**Поведение для `forward` и `head` **
``` sql
ALTER TABLE test_flow DELETE WHERE 1 = 1 settings mutations_sync = 1;
INSERT INTO test_flow VALUES (1, 1, 'Home') (2, 1, 'Gift') (3, 1, 'Exit');
INSERT INTO test_flow VALUES (1, 2, 'Home') (2, 2, 'Home') (3, 2, 'Gift') (4, 2, 'Basket');
INSERT INTO test_flow VALUES (1, 3, 'Gift') (2, 3, 'Home') (3, 3, 'Gift') (4, 3, 'Basket');
```
``` sql
SELECT id, sequenceNextNode('forward', 'head')(dt, page, page = 'Home', page = 'Home', page = 'Gift') FROM test_flow GROUP BY id;
2021-07-29 15:20:55 +00:00
2021-06-13 13:25:00 +00:00
dt id page
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 1 Home // Исходная точка, совпадение с Home
1970-01-01 09:00:02 1 Gift // Совпадение с Gift
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:03 1 Exit // Результат
2021-06-13 13:25:00 +00:00
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 2 Home // Исходная точка, совпадение с Home
1970-01-01 09:00:02 2 Home // Несовпадение с Gift
2021-06-13 13:25:00 +00:00
1970-01-01 09:00:03 2 Gift
2021-07-29 15:27:50 +00:00
1970-01-01 09:00:04 2 Basket
2021-07-29 15:20:55 +00:00
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 3 Gift // Исходная точка, несовпадение с Home
2021-07-29 15:27:50 +00:00
1970-01-01 09:00:02 3 Home
1970-01-01 09:00:03 3 Gift
1970-01-01 09:00:04 3 Basket
2021-06-13 13:25:00 +00:00
```
**Поведение для `backward` и `tail` **
``` sql
SELECT id, sequenceNextNode('backward', 'tail')(dt, page, page = 'Basket', page = 'Basket', page = 'Gift') FROM test_flow GROUP BY id;
dt id page
1970-01-01 09:00:01 1 Home
1970-01-01 09:00:02 1 Gift
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:03 1 Exit // Исходная точка, несовпадение с Basket
2021-07-29 15:27:50 +00:00
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:01 2 Home
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:02 2 Home // Результат
1970-01-01 09:00:03 2 Gift // Совпадение с Gift
1970-01-01 09:00:04 2 Basket // Исходная точка, совпадение с Basket
2021-07-29 15:27:50 +00:00
2021-06-13 13:25:00 +00:00
1970-01-01 09:00:01 3 Gift
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:02 3 Home // Результат
1970-01-01 09:00:03 3 Gift // Исходная точка, совпадение с Gift
1970-01-01 09:00:04 3 Basket // Исходная точка, совпадение с Basket
2021-06-13 13:25:00 +00:00
```
**Поведение для `forward` и `first_match` **
``` sql
SELECT id, sequenceNextNode('forward', 'first_match')(dt, page, page = 'Gift', page = 'Gift') FROM test_flow GROUP BY id;
dt id page
1970-01-01 09:00:01 1 Home
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:02 1 Gift // Исходная точка
1970-01-01 09:00:03 1 Exit // Результат
2021-07-29 15:27:50 +00:00
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:01 2 Home
1970-01-01 09:00:02 2 Home
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:03 2 Gift // Исходная точка
1970-01-01 09:00:04 2 Basket Результат
2021-07-29 15:27:50 +00:00
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 3 Gift // Исходная точка
1970-01-01 09:00:02 3 Home // Результат
2021-07-29 15:27:50 +00:00
1970-01-01 09:00:03 3 Gift
1970-01-01 09:00:04 3 Basket
2021-06-13 13:25:00 +00:00
```
``` sql
SELECT id, sequenceNextNode('forward', 'first_match')(dt, page, page = 'Gift', page = 'Gift', page = 'Home') FROM test_flow GROUP BY id;
dt id page
1970-01-01 09:00:01 1 Home
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:02 1 Gift // Исходная точка
1970-01-01 09:00:03 1 Exit // Несовпадение с Home
2021-07-29 15:27:50 +00:00
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:01 2 Home
1970-01-01 09:00:02 2 Home
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:03 2 Gift // Исходная точка
1970-01-01 09:00:04 2 Basket // Несовпадение с Home
2021-07-29 15:27:50 +00:00
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 3 Gift // Исходная точка
1970-01-01 09:00:02 3 Home // Совпадение с Home
1970-01-01 09:00:03 3 Gift // Результат
2021-07-29 15:27:50 +00:00
1970-01-01 09:00:04 3 Basket
2021-06-13 13:25:00 +00:00
```
**Поведение для `backward` и `last_match` **
``` sql
SELECT id, sequenceNextNode('backward', 'last_match')(dt, page, page = 'Gift', page = 'Gift') FROM test_flow GROUP BY id;
dt id page
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 1 Home // Результат
1970-01-01 09:00:02 1 Gift // Исходная точка
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:03 1 Exit
2021-07-29 15:27:50 +00:00
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:01 2 Home
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:02 2 Home // Результат
1970-01-01 09:00:03 2 Gift // Исходная точка
2021-07-29 15:27:50 +00:00
1970-01-01 09:00:04 2 Basket
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:01 3 Gift
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:02 3 Home // Результат
1970-01-01 09:00:03 3 Gift // Исходная точка
2021-07-29 15:27:50 +00:00
1970-01-01 09:00:04 3 Basket
2021-06-13 13:25:00 +00:00
```
``` sql
SELECT id, sequenceNextNode('backward', 'last_match')(dt, page, page = 'Gift', page = 'Gift', page = 'Home') FROM test_flow GROUP BY id;
dt id page
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 1 Home // Совпадение с Home, результат `Null`
1970-01-01 09:00:02 1 Gift // Исходная точка
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:03 1 Exit
2021-07-29 15:27:50 +00:00
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 2 Home // Результат
1970-01-01 09:00:02 2 Home // Совпадение с Home
1970-01-01 09:00:03 2 Gift // Исходная точка
2021-07-29 15:27:50 +00:00
1970-01-01 09:00:04 2 Basket
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 3 Gift // Результат
1970-01-01 09:00:02 3 Home // Совпадение с Home
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:03 3 Gift // Исходная точка
2021-07-29 15:27:50 +00:00
1970-01-01 09:00:04 3 Basket
2021-06-13 13:25:00 +00:00
```
**Поведение для `base_condition` **
``` sql
CREATE TABLE test_flow_basecond
(
`dt` DateTime,
`id` int,
`page` String,
`ref` String
)
ENGINE = MergeTree
PARTITION BY toYYYYMMDD(dt)
ORDER BY id;
INSERT INTO test_flow_basecond VALUES (1, 1, 'A', 'ref4') (2, 1, 'A', 'ref3') (3, 1, 'B', 'ref2') (4, 1, 'B', 'ref1');
```
``` sql
SELECT id, sequenceNextNode('forward', 'head')(dt, page, ref = 'ref1', page = 'A') FROM test_flow_basecond GROUP BY id;
2021-07-29 15:20:55 +00:00
dt id page ref
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 1 A ref4 // Начало не может быть исходной точкой, поскольку столбец ref не соответствует 'ref1'.
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:02 1 A ref3
1970-01-01 09:00:03 1 B ref2
1970-01-01 09:00:04 1 B ref1
2021-06-13 13:25:00 +00:00
```
``` sql
SELECT id, sequenceNextNode('backward', 'tail')(dt, page, ref = 'ref4', page = 'B') FROM test_flow_basecond GROUP BY id;
2021-07-29 15:20:55 +00:00
dt id page ref
2021-06-13 13:25:00 +00:00
1970-01-01 09:00:01 1 A ref4
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:02 1 A ref3
1970-01-01 09:00:03 1 B ref2
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:04 1 B ref1 // Конец не может быть исходной точкой, поскольку столбец ref не соответствует 'ref4'.
2021-06-13 13:25:00 +00:00
```
``` sql
SELECT id, sequenceNextNode('forward', 'first_match')(dt, page, ref = 'ref3', page = 'A') FROM test_flow_basecond GROUP BY id;
2021-07-29 15:20:55 +00:00
dt id page ref
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:01 1 A ref4 // Эта строка не может быть исходной точкой, поскольку столбец ref не соответствует 'ref3'.
1970-01-01 09:00:02 1 A ref3 // Исходная точка
1970-01-01 09:00:03 1 B ref2 // Результат
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:04 1 B ref1
2021-06-13 13:25:00 +00:00
```
``` sql
SELECT id, sequenceNextNode('backward', 'last_match')(dt, page, ref = 'ref2', page = 'B') FROM test_flow_basecond GROUP BY id;
2021-07-29 15:20:55 +00:00
dt id page ref
2021-06-13 13:25:00 +00:00
1970-01-01 09:00:01 1 A ref4
2021-06-14 12:39:53 +00:00
1970-01-01 09:00:02 1 A ref3 // Результат
1970-01-01 09:00:03 1 B ref2 // Исходная точка
2021-07-29 15:20:55 +00:00
1970-01-01 09:00:04 1 B ref1 // Эта строка не может быть исходной точкой, поскольку столбец ref не соответствует 'ref2'.
2021-06-13 13:25:00 +00:00
```