MATCH_RECOGNIZE 的核心能力是行序列建模与状态转移匹配:基于 ORDER BY 序列,按业务模式(如 A B+ C)分组相邻行并输出聚合结果;须配合 PARTITION BY 和 ORDER BY,使用 PREV() 等内置函数,慎选 ONE/ALL ROWS PER MATCH。

什么是 MATCH_RECOGNIZE 的核心能力
MATCH_RECOGNIZE 不是普通 WHERE 过滤,它在结果集上做「行序列建模」:把相邻行按业务逻辑分组(比如“连续上涨三天”),再对每组输出一行聚合结果。关键在于它天然支持「状态转移」——类似正则表达式匹配字符串,只不过对象是查询出的行序列。
必须满足两个前提才值得用:ORDER BY 列明确(时间戳、序号等);模式有明确起止条件和中间状态(如 A B+ C 表示“先出现 A,接着至少一个 B,最后以 C 结尾”)。
写基础模式时最容易漏掉 PARTITION BY 和 ORDER BY
没有 PARTITION BY,整个结果集被当做一个大序列处理,跨用户、跨设备的数据会混在一起匹配;没有 ORDER BY,数据库无法确定“连续”关系,MATCH_RECOGNIZE 会报错或返回不可靠结果。
- 错误写法:
MATCH_RECOGNIZE (PATTERN (A B) DEFINE A AS price > 100, B AS price —— 缺少PARTITION BY user_id ORDER BY event_time - 正确结构:
MATCH_RECOGNIZE (PARTITION BY user_id ORDER BY event_time PATTERN (A B) DEFINE A AS price > 100, B AS price - 注意:
ORDER BY列必须出现在 SELECT 或原始子查询中,否则报错ORA-62503: pattern matching ORDER BY expression not found in row pattern input
DEFINE 子句里不能用聚合函数或窗口函数
DEFINE 中每个变量(如 A、B)代表单行是否满足条件,所以只能写标量布尔表达式。常见误用是想判断“当前行价格比前一行高”,却直接写 price > LAG(price) —— LAG 是窗口函数,不被允许。
- 可行替代:
A AS price > PREV(price)(PREV()是MATCH_RECOGNIZE内置导航函数) - 连续三日上涨可写为:
PATTERN (X Y Z) DEFINE X AS price > 0, Y AS price > PREV(price), Z AS price > PREV(price) - 若需跨多行比较(如“当日高于前三日均值”),得先在外层子查询中算好辅助列,再传入
MATCH_RECOGNIZE
ONE ROW PER MATCH vs ALL ROWS PER MATCH 的性能差异很大
默认是 ONE ROW PER MATCH,每组匹配只返回一行(含聚合信息如 FIRST()、LAST()、CLASSIFIER());而 ALL ROWS PER MATCH 会为组内每一行都复制输出一次,数据量可能暴增数倍。
- 查“每个下跌周期的起止时间” → 用
ONE ROW PER MATCH,配合FIRST(event_time) AS start_time, LAST(event_time) AS end_time - 查“哪些行属于某个异常模式” → 用
ALL ROWS PER MATCH WITH UNMATCHED ROWS,但要注意未匹配行也会输出,需用classifier()过滤 - Oracle 12c 起支持
MEASURES中定义别名,但所有MEASURES表达式必须在DEFINE所依赖的列基础上计算,不能引入新列
复杂模式下,MATCH_RECOGNIZE 的执行计划容易出现 WINDOW SORT 和大量内存消耗,实际使用前务必在真实数据量级上 EXPLAIN PLAN 验证。









