Learning Platform
Глоссарий Troubleshooting
Урок 14.02 · 30 мин
Продвинутый
sequenceMatchsequenceCountevent sequencestemporal conditionspattern syntax

sequenceMatch и sequenceCount: детекция последовательностей

windowFunnel отвечает на вопрос “до какого шага дошёл пользователь”. sequenceMatch отвечает на вопрос “произошла ли конкретная последовательность событий?” sequenceCount — “сколько раз произошла эта последовательность?” Оба используют гибкий паттерн-синтаксис с поддержкой временных условий.


sequenceMatch: бинарный детектор паттернов

sequenceMatch('pattern')(timestamp, cond1, cond2, ...)

Возвращает UInt8: 1 если паттерн найден, 0 если нет.

  • timestamp — DateTime или UInt32 (временная метка события)
  • cond1, cond2, ... — логические выражения (условия), до 32 штук
  • 'pattern' — строка паттерна, описывающая нужную последовательность

Синтаксис паттернов

ЭлементЗначение
(?1)Условие 1 выполнено (первое условие в списке)
(?2)Условие 2 выполнено (второе условие в списке)
.*Любые события между (ноль или больше)
(?t<=1800)Не более 1800 секунд прошло с предыдущего совпавшего события
(?t>=60)Не менее 60 секунд прошло с предыдущего совпавшего события
(?1).*(?2)Условие 1, затем условие 2 с любым промежутком
(?1)(?t<=1800)(?2)Условие 1, затем условие 2 в пределах 30 минут
(?1)(?2)Условие 1, непосредственно за ним условие 2

Условия нумеруются от 1 до 32 в порядке их перечисления в вызове функции.


Примеры sequenceMatch

-- Пользователь просмотрел товар, а затем купил -- в любое время
SELECT
    user_id,
    sequenceMatch('(?1).*(?2)')(
        ts,
        event_type = 'view',
        event_type = 'purchase'
    ) AS ever_converted
FROM events
GROUP BY user_id;
-- Пользователь просмотрел, а затем купил -- в пределах 30 минут
SELECT
    user_id,
    sequenceMatch('(?1)(?t<=1800)(?2)')(
        ts,
        event_type = 'view',
        event_type = 'purchase'
    ) AS quick_convert
FROM events
GROUP BY user_id;
-- Сложный паттерн: поиск, затем просмотр, затем покупка в пределах часа
SELECT
    user_id,
    sequenceMatch('(?1).*(?2)(?t<=3600)(?3)')(
        ts,
        event_type = 'search',
        event_type = 'view',
        event_type = 'purchase'
    ) AS search_to_buy
FROM events
GROUP BY user_id;

sequenceCount: подсчёт непересекающихся цепочек

sequenceCount('pattern')(timestamp, cond1, cond2, ...)

Возвращает UInt64 — число непересекающихся вхождений паттерна.

-- Сколько раз пользователь делал поиск, а затем кликал на результат?
SELECT
    user_id,
    sequenceCount('(?1).*(?2)')(
        ts,
        event_type = 'search',
        event_type = 'click'
    ) AS search_click_pairs
FROM events
GROUP BY user_id
ORDER BY search_click_pairs DESC
LIMIT 10;

“Непересекающиеся” означает: после нахождения паттерна поиск продолжается с позиции после последнего совпавшего события, а не с начала. Это предотвращает многократный счёт одной и той же цепочки.


Сравнение: sequenceMatch vs sequenceCount vs windowFunnel

ФункцияЧто возвращаетКогда использовать
windowFunnelUInt8 — максимальный шаг воронкиАнализ конверсионной воронки (до какого шага дошёл)
sequenceMatchUInt8 (0 или 1) — было/не былоДетекция конкретного паттерна поведения
sequenceCountUInt64 — число вхожденийПодсчёт повторяющихся паттернов (сессий, попыток)
-- Пример: сравнение трёх подходов на одних данных
SELECT
    user_id,
    windowFunnel(86400)(ts, event_type='view', event_type='cart', event_type='purchase') AS funnel_level,
    sequenceMatch('(?1).*(?2)')(ts, event_type='view', event_type='purchase')            AS ever_bought_after_view,
    sequenceCount('(?1).*(?2)')(ts, event_type='search', event_type='purchase')          AS search_to_buy_count
FROM events
GROUP BY user_id;

Ограничение: отрицательные условия

sequenceMatch не поддерживает прямое отрицание шагов. Нельзя написать “пользователь сделал A, не сделал B, потом сделал C” как единый паттерн.

-- Такого синтаксиса НЕ существует:
-- sequenceMatch('(?1)(?!2).*(?3)')(ts, cond1, cond2, cond3)  -- ошибка

-- Обходной путь: разделить на два запроса
-- Запрос 1: найти пользователей с паттерном A -> C
-- Запрос 2: исключить тех, у кого было B между A и C
WARNING

sequenceMatch не поддерживает отрицательные условия в паттерне. Для логики “A произошло, B не произошло, C произошло” используйте комбинацию sequenceMatch с HAVING или вложенными запросами. Прямого синтаксиса для отрицания шага нет.


Ключевые выводы

  1. sequenceMatch('(?1).*(?2)')(ts, cond1, cond2) — детектор паттерна; возвращает 0 или 1.
  2. sequenceCount('(?1).*(?2)')(ts, cond1, cond2) — счётчик непересекающихся вхождений; возвращает UInt64.
  3. Временные условия (?t<=N) и (?t>=N) задают максимальный и минимальный интервал между событиями в секундах.
  4. До 32 условий: (?1) через (?32) — нумерация в порядке перечисления в вызове функции.
  5. Отрицательные условия не поддерживаются — для таких сценариев нужны составные запросы.
  6. Выбор функции: windowFunnel — для воронки (до какого шага), sequenceMatch — было/не было, sequenceCount — сколько раз.
Spark Structured Streaming: session windows и event-driven aggregations Event schema design: event types, properties и temporal ordering

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 3. sequenceMatch('(?1)(?t<=1800)(?2)')(ts, event_type='search', event_type='purchase') -- что означает (?t<=1800) в этом паттерне?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 8