当前位置:网站首页>92 match for several_ Recognize SQL write example
92 match for several_ Recognize SQL write example
2022-06-22 21:23:00 【Tiger Liu】
stay SQL Support row matching pattern in match_recognize How to write it , yes oracle from 12c Starting with , It's very powerful , The grammar seems a little complicated , With ordinary SQL Very different .
oracle When introducing this new method , Take one example to get a stock V Type diagram (2 A peak and a valley ) Example ( There are many introductions on the Internet , Are used in this example ), But except for this example , There are few other application cases , Here is a place to throw a brick at , Introduce some examples of match_recognize Solutions to problems , For reference only .
Example (1) : Remove the continuous repetition state , Keep only the first , Here's the picture , The red lines are the records that need to be removed
This problem is also relatively simple if it is implemented with an analysis function , The following is to use match_recognize Method of implementation :
with d (type,dt,status)as
( select 'X' ,date '2021-7-1','1' from dual
union all select 'X' ,date '2021-7-2','1' from dual
union all select 'X' ,date '2021-7-3','0' from dual
union all select 'X' ,date '2021-7-4','0' from dual
union all select 'X' ,date '2021-7-5','1' from dual
union all select 'X' ,date '2021-7-6','0' from dual
union all select 'X' ,date '2021-7-7','0' from dual
union all select 'X' ,date '2021-7-8','0' from dual
union all select 'X' ,date '2021-7-9','1' from dual
union all select 'X' ,date '2021-7-10','1' from dual
union all select 'X' ,date '2021-7-11','1' from dual
)
SELECT *
FROM d
MATCH_RECOGNIZE (
PARTITION BY type
ORDER BY dt
measures
dt as dt,
status as status
one ROW PER MATCH
PATTERN ( A )
DEFINE
A as status<>prev(status) or prev(status) is null
);
There are other ways to write , You can get the same result , Here is itpub The writing method of master Su, the moderator of the development Edition :
with d (type,dt,status)as
( select 'X' ,date '2021-7-1','1' from dual
union all select 'X' ,date '2021-7-2','1' from dual
union all select 'X' ,date '2021-7-3','0' from dual
union all select 'X' ,date '2021-7-4','0' from dual
union all select 'X' ,date '2021-7-5','1' from dual
union all select 'X' ,date '2021-7-6','0' from dual
union all select 'X' ,date '2021-7-7','0' from dual
union all select 'X' ,date '2021-7-8','0' from dual
union all select 'X' ,date '2021-7-9','1' from dual
union all select 'X' ,date '2021-7-10','1' from dual
union all select 'X' ,date '2021-7-11','1' from dual
)
SELECT *
FROM d
MATCH_RECOGNIZE (
PARTITION BY type
ORDER BY dt
ALL ROWS PER MATCH
PATTERN ( (A|{-B-})+ )
DEFINE
A as status<>last(status,1) or prev(status) is null
);
You can compare the difference between the two .
Example (2): Get the number of records whose subsequent record value is greater than the current record value , For example, the following result set
The two columns on the left are the original records , The last column is match_recognize Results after . The first record val yes 4, below 9 Condition records , All ratio 4 Big , cnt Namely 9; Second val yes 10, The next is 10 The big records are 12 and 14, cnt Namely 2, And so on .
with gen as
(select rownum as ID, round(dbms_random.value(3,15)) as val
from dual connect by level<=10
)
select * from gen
match_recognize(
order by id
measures
first(a.id) as id,
first(a.val) as val,
final count(b.*) as cnt
one row per match
after match skip to next row
pattern (a (b|c)* )
define
b as b.val>a.val,
c as c.val<=a.val
);
( There are many ways to realize this function , Here only talk about match_recognize Writing )
Example (3): Get the total salary of all employees and all subordinates
select * from
(
select level lvl, ename, sal
from scott.emp
start with mgr is null
connect by mgr = prior empno
)
match_recognize
(
measures
a.lvl lvl, a.ename ename,a.sal sal,
sum(sal) as sum_sal
after match skip to next row
pattern(a b*)
define b as lvl > a.lvl
);
Result set :
The first record lvl=1, All the records below lvl all <1,sum_sal Equivalent to the total salary of the whole company ; Article 2 record lvl=2, To the next lvl=2 Sum of all records before =10875(2975+3000+1100+3000+800 ), And so on .
Example (4) : Merge continuous intervals
with tmp(id ,page) as
(select 1 ,3 from dual union all select 2,4 from dual union all
select 4,8 from dual union all select 3,5 from dual union all
select 5,9 from dual union all select 6,16 from dual union all
select 7,15 from dual union all select 8,18 from dual
)
SELECT *
FROM tmp
MATCH_RECOGNIZE
(
ORDER BY page
MEASURES
A.page as firstpage,
LAST(page) as lastpage,
COUNT(*) cnt
ONE ROW PER MATCH
AFTER MATCH SKIP PAST LAST ROW
PATTERN (A B*)
DEFINE B AS page = PREV(page)+1
);
Result set ( On the left is before the merger ):
among : 3~5 Is a continuous 3 It's worth ; 8~9 Is a continuous 2 It's worth ...
Example (5) : Calculate continuous 3 God ( The interval between the first record and the third record shall not exceed 3 God ) And
In official account 73- Find the business peak hours sql Example ( Report development class ) in , In the message section, I added the analysis function and model Writing , Here's one more match_recognize Writing , There is no need to supplement what does not exist " God ", The simulation data is used to demonstrate the following :
with gen (id, val) as
(select 1, 3 from dual union all select 2, 2 from dual union all select 3,5 from dual union all
select 5, 3 from dual union all select 8, 2 from dual union all select 9,5 from dual union all
select 10, 3 from dual union all select 12, 2 from dual union all select 13,5 from dual union all
select 14, 3 from dual union all select 15, 2 from dual union all select 16,5 from dual union all
select 20, 3 from dual union all select 21, 2 from dual union all select 23,5 from dual
)
select bid,bid+2 as eid,sum3 from gen
match_recognize(
order by id
measures
first (a.id) as bid,
sum(val) as sum3
one row per match
after match skip to next row
pattern (A B*)
define
B as b.id<=a.id+2
);
Result set ( On the left is the raw data , On the right is match_recognize After the results of the ):
After getting the result set on the right , It can be further processed ( For example, re select top 5 etc. )
Example (6) : come from itpub Master Su's weekly question
http://www.itpub.net/thread-2117353-1-1.html
create table qz_game_log (
seq integer primary key
, log varchar2(10)
);
insert into qz_game_log values (117, 'GO');
insert into qz_game_log values (118, 'LEFT');
insert into qz_game_log values (119, 'LEFT');
insert into qz_game_log values (120, 'RIGHT');
insert into qz_game_log values (121, 'LEFT');
insert into qz_game_log values (122, 'FINISH');
insert into qz_game_log values (123, 'GO');
insert into qz_game_log values (124, 'RIGHT');
insert into qz_game_log values (125, 'RIGHT');
insert into qz_game_log values (126, 'LEFT');
insert into qz_game_log values (127, 'CRASH');
insert into qz_game_log values (128, 'GO');
insert into qz_game_log values (129, 'RIGHT');
insert into qz_game_log values (130, 'LEFT');
insert into qz_game_log values (131, 'RIGHT');
insert into qz_game_log values (132, 'LEFT');
insert into qz_game_log values (133, 'RIGHT');
insert into qz_game_log values (134, 'FINISH');
commit;
Every game is from GO Start , Then there is a series of LEFT perhaps RIGHT Move , And then to FINISH perhaps CRASH End .
The game that ends successfully is FINISH instead of CRASH End , I want to see all the successful Games LEFT/RIGHT Move steps ,
From which SEQ To which SEQ end , I also want to know how many steps , among RIGHT A few steps ,LEFT A few steps .
GO and FINISH Not counted in the game's move steps .
Required output :
FROM_SEQ TO_SEQ MOVES RIGHTS LEFTS
---------- ---------- ---------- ---------- ----------
118 121 4 1 3
129 133 5 3 2
Two ways of writing given by the original author , Worth learning :
How to write it 1)
select min(seq) as from_seq
, max(seq) as to_seq
, count(*) as moves
, count(case cls when 'RIGHT' then 1 end) as rights
, count(case cls when 'LEFT' then 1 end) as lefts
from qz_game_log
match_recognize (
measures
match_number() as mno
, classifier() as cls
ALL ROWS PER MATCH
pattern ({-GO-} (LEFT|RIGHT)+ {-FINISH-})
define
GO as log = 'GO'
, LEFT as log = 'LEFT'
, RIGHT as log = 'RIGHT'
, FINISH as log = 'FINISH'
)
GROUP BY mno
order by from_seq;
How to write it 2)
select from_seq, to_seq, moves, rights, lefts
from qz_game_log
match_recognize (
measures
min(MOVE.seq) as from_seq
, max(MOVE.seq) as to_seq
, count(MOVE.seq) as moves
, count(RIGHT.seq) as rights
, count(LEFT.seq) as lefts
one row per match
pattern (GO (LEFT|RIGHT)+ FINISH)
SUBSET
MOVE = (LEFT, RIGHT)
define
GO as log = 'GO'
, LEFT as log = 'LEFT'
, RIGHT as log = 'RIGHT'
, FINISH as log = 'FINISH'
)
order by from_seq;
How to write it 3) This is the way I try to write ( All roads lead to Rome , There should be no difference in performance ):
select * from qz_game_log
match_recognize(
order by seq
measures
least(first(l.seq) , first(r.seq) ) as from_seq,
greatest(last(l.seq) , last(r.seq) ) as to_seq,
count(l.*)+count(r.*) as moves,
count(r.*) as rights,
count(l.*) as lefts
one row per match
pattern
( strt (L|R)+ fini )
define
strt as log='GO',
L as log='LEFT',
R as log='RIGHT',
fini as log='FINISH'
);
use match_recognize There are many other cases related to line to line matching , There are also some that implement complex business logic . Here are some simple examples , Let's talk about match_recognize Have a general understanding of the usage of .
match_recognize There should be more application scenarios in the financial industry ( Such as stock analysis and suspicious transaction analysis ), After the developers are familiar with this function , You can easily use SQL Implementing complex business logic .
边栏推荐
猜你喜欢

R language Midwest dataset visualization

【206. 反转链表】

访问成功但抛出异常:Could not find acceptable representation

优化求解器 | Gurobi的MVar类:矩阵建模利器、求解对偶问题的备选方案 (附详细案例+代码)
![[palindrome structure of or36 linked list]](/img/67/33730a30c715db573e1d4f7e5556da.png)
[palindrome structure of or36 linked list]
![[redis] publish and subscribe](/img/50/0c2fbbb8f56fccdd3222b77efdd723.png)
[redis] publish and subscribe

redis学习笔记

2022年山东省安全员C证考试试题模拟考试平台操作
![[redis]发布与订阅](/img/50/0c2fbbb8f56fccdd3222b77efdd723.png)
[redis]发布与订阅

Simulated 100 questions and simulated examination of hoisting machinery command examination in 2022
随机推荐
es 按条件查询数据总条数
[palindrome structure of or36 linked list]
Fluent system architecture
杰理之MUSIC 模式获取播放文件的目录【篇】
80- paging query, not only writing
使用Charles抓包
Notes d'apprentissage de golang - structure
PlainSelect. getGroupBy()Lnet/sf/jsqlparser/statement/select/GroupByElement;
嵌入式开发基础之任务管理(线程管理)
优化求解器 | Gurobi的MVar类:矩阵建模利器、求解对偶问题的备选方案 (附详细案例+代码)
php 镜像制作
长安旗下阿维塔科技增资扩股落定:宁德时代将持股约24%!
[20. valid brackets]
ACM. HJ45 名字的漂亮度 ●●
【142. 环形链表 II】
78- several methods to solve SQL performance problems without changing code in production system
评估指标及代码实现(NDCG)
2022年山东省安全员C证考试试题模拟考试平台操作
【138. 复制带随机指针的链表】
百家讲坛 黄帝内经(第一部)