假设现在有两个表
表一:
idnum
sname
score
140643851
小A
87
140643856
小B
88
140643931
小C
92
140643611
小D
77
140643427
小E
81
140643155
小F
95
140643815
小G
78
140643492
小H
90
140643653
小I
71
表二:
id
oname
event
1001
小a
小a在2017-10-19通知了学号为140643851,140643856的学生
1003
小b
小b在2017-10-03通知了学号为140643931的学生
1005
小c
小c在2017-10-08通知了学号为140643611,140643427,140643155的学生
表一的id是学号,表二的event中的数字就是学号,现在要查出这样的表
id
oname
idnum
sname
那怎么做呢?
第一步,要把表二中的学号匹配出来吧?用正则表达式就好啦
‘[0-9]{9}(,[0-9]{9})*’
注意这里的数字是9位,后面可能有若干个逗号加数字,所以用括号括起来,用了‘*’
这个’*’就是零个或者多个的意思啦,{9}表示这样的数字有9位。有关正则可以看这一篇博客总结http://blog.csdn.net/yolanda_nuonuo/article/details/50524758
然后用oracle里的正则函数
regexp_substr(t.event, ‘[0-9]{9}(,[0-9]{9})*’),这个就可以把数字取出来了。
第二步,第一步的做法拿到的是这样的数字,这个表是test_tb,一个辅助中间表
value
140643851,140643856
140643931
140643611,140643427,140643155
但是要跟表一关联的话,需要的是这样的数字
学号
140643851
140643856
140643931
140643611
140643427
140643155
这个要怎么做呢?用connect by.
SELECT distinct regexp_substr(t.value, '[^,]+',1,level)
FROM test_tb t
CONNECT BY t.value = PRIOR t.value
AND LEVEL <= (length(t.value)-length(regexp_replace(t.value, ',', '')))+1
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
说明:
这里的level就是一个层级的概念,比如吧
学号
140643851,140643856
140643931
140643611,140643427,140643155
这个第三列,有三个数,就有三层,level就要小于3
所以就要先算出这列有几个数据,可以用下面这句sql试一下
select t.value, (length(t.value)-length(regexp_replace(t.value, ',', '')))+1 from test_tb t
其实就是算出逗号的个数再加一就是有几个数。
最后的sql就是这样啦
select op.id, op.oname, tu.idnum, tu.sname from
(
select distinct to_number(regexp_substr(tb.value, '[^,]+',1,level)) as tid, tb.oid as oid from
(
select regexp_substr(o.event, '[0-9]{9}(,[0-9]{9})*') as value, o.id as oid from test_oper o
where regexp_substr(o.event, '[0-9]{9}(,[0-9]{9})*') is not null) tb
CONNECT BY TB.value = PRIOR TB.value
AND LEVEL <= (length(tb.value)-length(regexp_replace(tb.value, ',', '')))+1
AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
)
mm, test_stu tu, test_oper op
where mm.tid = tu.idnum
and mm.oid = op.id
结果就是
这里临时自定义了几个表,为了对应关系