搜索模式并删除搜索字符串字符(如果找不到),然后在oracle sql中再次搜索

时间:2018-08-19 08:31:21

标签: sql oracle plsql pattern-matching

我必须编写一个查询,其中包含如下所示的where子句:

setBcc()

现在我的要求是,如果上面的查询没有返回任何内容,则使用678或789或67或89搜索。

我如何以最佳的优化方式实现这一目标?

2 个答案:

答案 0 :(得分:2)

一次搜索包含6、7、8或9的任何值,并按该值与'6789'的匹配程度进行排序,然后得出最高的结果。

(编辑:我添加了一个instr表达式以优先于JW分数优先出现确切的字符串'6789',否则'678 blah'的排名将高于'blah 6789'

create table demo (col1) as
( select column_value
  from   table(sys.dbms_debug_vc2coll
         ( '6789','678X','X789','67XX','XX89','XXXX','6XXX','X7XX','11111167891111'
         , '167891','Germany 6, England 7 what a great match that was in 1989')) );

select col1
     , utl_match.jaro_winkler_similarity(col1,'6789') as match_rating
     , nullif(instr(col1,'6789'),0) as match_position
from   demo
where  regexp_like(col1,'[6789]')
order by match_position nulls last, match_rating desc;

COL1                                                     MATCH_RATING MATCH_POSITION
-------------------------------------------------------- ------------ --------------
6789                                                              100              1
167891                                                             88              2
11111167891111                                                     59              7
678X                                                               88 
X789                                                               83 
67XX                                                               73 
XX89                                                               66 
6XXX                                                               55 
X7XX                                                               50 
Germany 6, England 7 what a great match that was in 1989           34 

10 rows selected

过滤以获取第一行(从Oracle 12.1开始):

select col1
from   demo
where  regexp_like(col1,'[6789]')
order by
       nullif(instr(col1,'6789'),0) nulls last
     , utl_match.jaro_winkler_similarity(col1,'6789') desc
fetch first row only;

COL1
-----
6789

对于旧版本:

select col1
from   ( select col1
         from   demo
         where  regexp_like(col1,'[6789]')
         order by
                nullif(instr(col1, '6789'),0) nulls last
              , utl_match.jaro_winkler_similarity(col1,'6789') desc )
where rownum = 1;

http://sqlfiddle.com/#!4/a9d884/3

注意'6789'可以用PL / SQL中的变量替换:

select col1 into :result
from   demo
where  regexp_like(col1,'['||p_pattern||']')
order by
       nullif(instr(col1, p_pattern),0) nulls last
     , utl_match.jaro_winkler_similarity(col1,p_pattern) desc
fetch first row only;

答案 1 :(得分:0)

您可以将UNION ALLNOT EXISTS结合使用,this answer来实现按顺序执行不同的选择,类似于{{3}}

select x from table where col1 like '%6789%'
UNION ALL
select x from table where col1 like '%678%' or col1 like '%789%' 
or col1 like '%67%' or col1 like '%89%'
AND NOT EXISTS (
select x from table where col1 like '%6789%'
)