浅析REGEXP_SUBSTR,PRIOR,CONNECT BY
事务场景
teacher表中的tech_class字段存储的是每个教师所教授的课程,课程之间以英文逗号分隔。现在要用句子计算每个课程对应的教师数量。句子及作用如下:
句子其实很简略,各种博客或许gpt都有不错且可行的解决方案,咱们主要来理解下这段句子的履行原理,更好的学习。
part1 REGEXP_SUBSTR
关于REGEXP_SUBSTR的官方文档
详细语法这儿不再赘叙,咱们从单个比如下手看看作用:
REGEXP_SUBSTR能够将字段字符串依据所给正则表达式匹配并拆分(留意不是切割,但作用上等同于切割)。
最终一个参数代表要取出第几个匹配的成果:
那为什么这儿要运用LEVEL?LEVEL是什么?
关于LEVEL的官方解说 详细如图:
运用之前要留意,官方文档里有句话:
To define a hierarchical relationship in a query, you must use the CONNECT BY clause.
所以关于connect by,你能够先往后看。
运用LEVEL后的作用:
LEVEL是一个在CONNECT BY子句中运用的伪列,它代表当时递归层次的等级。在每次递归调用中,LEVEL的值会增加1。在这个比如中,LEVEL的值会从1开端,一直到tech_class中逗号分隔的子串的数量——3。
为什么这样会有81条?咱们的预期成果其实是3条。让咱们持续探求......
Football是字段里的第一个值,只要1条;Basketball是字段里的第二个值,有10条;PingPang是字段里的第三个值,有70条!形似越往后数据重复越多,并且次数增加的可怕,但很难发现出有什么规则。检索后根本确认呈现重复数据是因为在递归过程中,regexp_substr函数没有正确移动到下一个匹配项,而是重复移动到了Basketball或许PingPang,至于它底层是什么重复移动的,额我也没搞理解....。
对此咱们需求增加prior确保每次递归时都能正确提取。
part3 prior
关于prior的简略介绍
connect by中加prior能够限制父子的对应联系,限制递归途径。这儿对同条记载进行递归:
加sys_guid()是为了确保层次查询,存在循环时,不呈现无限递归。它为每行生成一个仅有标识,然后防止无限循环。
Part3 connect by
CONNECT BY的官方文档--分级查询
connect by常常结合prior一同完成父级查询。因而connect by LEVEL prior一般都一同呈现。
附
最终再次附上针对原始的事务需求的完好的句子及输出:
select
regexp_substr(tech_class, '[^,]+', 1, LEVEL) as class_name,
tech_name
from teacher
CONNECT BY LEVEL <= REGEXP_COUNT(tech_class, '[^,]+')
and prior tech_class = tech_class
and prior sys_guid() is not null
order by class_name