Advanced
Pattern Matching With MATCH_RECOGNIZE
`MATCH_RECOGNIZE` detects ordered event patterns over a timestamped stream.
Guide
`MATCH_RECOGNIZE` detects ordered event patterns over a timestamped stream.
Basic tested query:
SELECT mr.start_price, mr.end_price INTO output
FROM input TIMESTAMP BY ts
MATCH_RECOGNIZE (
LIMIT Duration(minute, 1)
MEASURES
A.price AS start_price,
B.price AS end_price
ONE ROW PER MATCH
AFTER MATCH SKIP TO NEXT ROW
PATTERN (A B)
DEFINE
A AS A.kind = 'A',
B AS B.kind = 'B'
) AS mrTested input:
{"ts":1,"kind":"A","price":10}
{"ts":2,"kind":"B","price":12}
{"ts":3,"kind":"A","price":20}
{"ts":4,"kind":"B","price":25}Tested output:
{"start_price":10,"end_price":12}
{"start_price":20,"end_price":25}The output event timestamp is the accepting event timestamp. In the test above, intermediate output arrival times are `2` and `4`.
MATCH_RECOGNIZE Grammar
FROM <input> TIMESTAMP BY <field>
MATCH_RECOGNIZE (
[PARTITION BY <field-path>[, ...]]
LIMIT Duration(<unit>, <value>)
MEASURES
<measure-expression> AS <alias>[, ...]
ONE ROW PER MATCH
AFTER MATCH SKIP TO NEXT ROW
PATTERN (<pattern-expression>)
DEFINE
<variable> AS <condition>[, ...]
) AS <alias>Supported and tested constraints:
- `TIMESTAMP BY` is required.
- `LIMIT Duration(...)` is required.
- An alias after `) AS` is required.
- `ONE ROW PER MATCH` is the supported row mode.
- `AFTER MATCH SKIP TO NEXT ROW` is the supported skip mode.
- Every primary pattern variable must have a `DEFINE`.
- Every `DEFINE` variable must appear in the `PATTERN`.
- Outer `SELECT` can reference measure names directly or through the match alias.
- Aggregate expressions in the outer `SELECT` are not supported for `MATCH_RECOGNIZE`.
- `MATCH_RECOGNIZE` cannot be combined with `WINDOW BY`, `GROUP BY`, or `HAVING`.
Partitioned Matching
Partitions keep independent match state per key.
SELECT device, first_value, last_value INTO output
FROM input TIMESTAMP BY ts
MATCH_RECOGNIZE (
PARTITION BY device
LIMIT Duration(minute, 1)
MEASURES
FIRST(A.value) AS first_value,
LAST(B.value) AS last_value
ONE ROW PER MATCH
AFTER MATCH SKIP TO NEXT ROW
PATTERN (A B)
DEFINE
A AS A.kind = 'start',
B AS B.kind = 'end'
) AS mrWith interleaved `X` and `Y` devices, the tests emit one match per device.
Measures
Tested measure expressions include:
A.price AS start_price
B.price AS end_price
FIRST(A.value) AS first_value
LAST(B.value) AS last_valueMeasures require aliases.
PREV Navigation
`PREV` compares the current variable binding to an earlier binding in the same pattern variable:
SELECT run_id, last_b INTO output
FROM input TIMESTAMP BY ts
MATCH_RECOGNIZE (
LIMIT Duration(minute, 1)
MEASURES
A.run_id AS run_id,
LAST(B.value) AS last_b
ONE ROW PER MATCH
AFTER MATCH SKIP TO NEXT ROW
PATTERN (A B{2})
DEFINE
A AS A.kind = 'A',
B AS B.kind = 'B' AND B.value > PREV(B.value)
) AS mrIn the tests, only the run whose `B` values increase from `10` to `20` matches.
Quantifiers
The tests cover these pattern quantifiers:
B* zero or more
B+ one or more
B? zero or one
B{2,} at least two
B{1,3} one to three
B{,2} zero to two
B{3} exactly threeExample with zero-or-more:
SELECT run_id, c_value INTO output
FROM input TIMESTAMP BY ts
MATCH_RECOGNIZE (
PARTITION BY run_id
LIMIT Duration(minute, 1)
MEASURES
C.value AS c_value
ONE ROW PER MATCH
AFTER MATCH SKIP TO NEXT ROW
PATTERN (A B* C)
DEFINE
A AS A.kind = 'A',
B AS B.kind = 'B',
C AS C.kind = 'C'
) AS mrExample with one-or-more:
SELECT run_id, c_value INTO output
FROM input TIMESTAMP BY ts
MATCH_RECOGNIZE (
PARTITION BY run_id
LIMIT Duration(minute, 1)
MEASURES
C.value AS c_value
ONE ROW PER MATCH
AFTER MATCH SKIP TO NEXT ROW
PATTERN (A B+ C)
DEFINE
A AS A.kind = 'A',
B AS B.kind = 'B',
C AS C.kind = 'C'
) AS mrAlternation and Complex Conditions
The parser supports pattern alternation and boolean conditions in `DEFINE`, with the same predicate family used by `WHERE` where covered by tests.
The tested syntax suite includes:
PATTERN (A B* C+ D? E{2,} F{1,3} G{,2} H{3})