简体   繁体   English

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

[英]Search pattern and remove search string characters if not found and then search it again in oracle sql

I have to write a query which is having a where clause like below: 我必须编写一个查询,其中包含如下所示的where子句:

select x from table where col1 like '%6789%';

Now the requirement I have is if above query doesn't return anything then search with 678 or 789 or 67 or 89. 现在我的要求是,如果上面的查询不返回任何内容,则使用678或789或67或89搜索。

How can I achieve this in best optimised way? 如何以最佳的方式实现这一目标?

Search once for any value containing 6, 7, 8 or 9, order by how well the value matches '6789' and take the top result. 一次搜索包含6、7、8或9的任何值,并按该值与'6789'匹配程度排序,并获得最高的结果。

(Edit: I've added an instr expression to prioritise occurrences of the exact string '6789' over the JW score, as otherwise '678 blah' would rank higher than 'blah 6789' .) (编辑:我添加了一个instr表达式以将确切字符串'6789'出现优先于JW分数,否则'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

Filter to get the first row (Oracle 12.1 onwards): 过滤以获取第一行(从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

For older versions: 对于旧版本:

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 http://sqlfiddle.com/#!4/a9d884/3

Note '6789' can be replaced with a variable in PL/SQL: 注意'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;

You can achieve executing different select with order using UNION ALL combined with NOT EXISTS , similar to this answer 您可以使用UNION ALL结合NOT EXISTS来实现按顺序执行不同的选择,类似于此答案

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%'
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM