我必须编写一个查询,其中包含如下所示的where子句:
setBcc()
现在我的要求是,如果上面的查询没有返回任何内容,则使用678或789或67或89搜索。
我如何以最佳的优化方式实现这一目标?
答案 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 ALL与NOT 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%'
)