如何让 REGEXP_LIKE 先得到确切的词,然后再附加所有相关的词?
How to get REGEXP_LIKE that gets the exact word first, then append all the word related later?
Table 描述:
id desc
0 ball
1 basketball
2 ballpen
3 a ball
4 ball pen
table 期望输出
id desc
0 ball
3 a ball
4 ball pen
2 ballpen
1 basketball
连顺序都不一样。
但重要的是,我首先要得到确切的词,然后是所有相关的词。 a ball 仍然被认为是准确的词,所以它可以是第一个。
我宁愿建议这样的东西,而不是正则表达式:UTL_MATCH
。
SQL> with test (id, c_desc) as
2 (select 0, 'ball' from dual union
3 select 1, 'basketball' from dual union
4 select 2, 'ballpen' from dual union
5 select 3, 'a ball' from dual union
6 select 4, 'ball pen' from dual union
7 select 5, 'littlefoot' from dual
8 )
9 select
10 id,
11 c_desc,
12 utl_match.jaro_winkler_similarity (c_desc, '&&par_desc') similarity
13 from test
14 where instr(c_desc, '&&par_desc') > 0
15 order by utl_match.jaro_winkler_similarity (c_desc, '&&par_desc') desc;
Enter value for par_desc: ball
ID C_DESC SIMILARITY
---------- ---------- ----------
0 ball 100
2 ballpen 91
4 ball pen 89
3 a ball 80
1 basketball 65
SQL> undefine par_desc
SQL> /
Enter value for par_desc: pinky
no rows selected
SQL> undefine par_desc
SQL> /
Enter value for par_desc: tle
ID C_DESC SIMILARITY
---------- ---------- ----------
5 littlefoot 65
SQL>
这里有两种方法 return 所有带有独立词 "ball" 的行,然后是包含 "ball" 的那些在另一个词中的行。
首先,如果您想确保只有 "ball" 的行首先出现,请在您的排序中构建一个 case 表达式。
在此检查该值是否等于您的搜索变量。如果它确实映射到一个数字,例如一个。如果它没有映射到更高的数字,例如二.
对于return所有包含ball的行,这里有两种方式:
regexp_like
您可以使用正则表达式:
(^|\s|\W)球($|\s|\W)
在 SQL 中看起来像:
create table t as
select 0 id, 'ball' val from dual union
select 1, 'basketball' from dual union
select 2, 'ballpen' from dual union
select 3, 'a ball' from dual union
select 4, 'ball pen' from dual union
select 5, 'littlefoot' from dual;
var v varchar2(10);
exec :v := 'ball';
select *
from t
where val like '%' || :v || '%'
order by case
when val = :v then 1
when regexp_like ( val, '(^|\s|\W)' || :v || '($|\s|\W)' ) then 2
else 3
end, id;
ID VAL
0 ball
3 a ball
4 ball pen
1 basketball
2 ballpen
Oracle 文本
如果在列上创建 Oracle Text 索引,则可以使用 contains 来查找匹配的行。调用两次。一次找到完全匹配。然后再次显示与单词的匹配。
然后按照分数从高到低排序。先是准确分数,再是其他:
create index test_i on t ( val ) indextype is ctxsys.context;
select t.*, score (1), score (2) from t
where contains ( val, :v, 1 ) > 0
or contains ( val, '%' || :v || '%', 2 ) > 0
order by case
when val = :v then 1
else 2
end, score ( 1 ) desc, score ( 2 ) desc;
ID VAL SCORE(1) SCORE(2)
0 ball 4 4
3 a ball 4 4
4 ball pen 4 4
1 basketball 0 4
2 ballpen 0 4
Table 描述:
id desc
0 ball
1 basketball
2 ballpen
3 a ball
4 ball pen
table 期望输出
id desc
0 ball
3 a ball
4 ball pen
2 ballpen
1 basketball
连顺序都不一样。 但重要的是,我首先要得到确切的词,然后是所有相关的词。 a ball 仍然被认为是准确的词,所以它可以是第一个。
我宁愿建议这样的东西,而不是正则表达式:UTL_MATCH
。
SQL> with test (id, c_desc) as
2 (select 0, 'ball' from dual union
3 select 1, 'basketball' from dual union
4 select 2, 'ballpen' from dual union
5 select 3, 'a ball' from dual union
6 select 4, 'ball pen' from dual union
7 select 5, 'littlefoot' from dual
8 )
9 select
10 id,
11 c_desc,
12 utl_match.jaro_winkler_similarity (c_desc, '&&par_desc') similarity
13 from test
14 where instr(c_desc, '&&par_desc') > 0
15 order by utl_match.jaro_winkler_similarity (c_desc, '&&par_desc') desc;
Enter value for par_desc: ball
ID C_DESC SIMILARITY
---------- ---------- ----------
0 ball 100
2 ballpen 91
4 ball pen 89
3 a ball 80
1 basketball 65
SQL> undefine par_desc
SQL> /
Enter value for par_desc: pinky
no rows selected
SQL> undefine par_desc
SQL> /
Enter value for par_desc: tle
ID C_DESC SIMILARITY
---------- ---------- ----------
5 littlefoot 65
SQL>
这里有两种方法 return 所有带有独立词 "ball" 的行,然后是包含 "ball" 的那些在另一个词中的行。
首先,如果您想确保只有 "ball" 的行首先出现,请在您的排序中构建一个 case 表达式。
在此检查该值是否等于您的搜索变量。如果它确实映射到一个数字,例如一个。如果它没有映射到更高的数字,例如二.
对于return所有包含ball的行,这里有两种方式:
regexp_like
您可以使用正则表达式:
(^|\s|\W)球($|\s|\W)
在 SQL 中看起来像:
create table t as
select 0 id, 'ball' val from dual union
select 1, 'basketball' from dual union
select 2, 'ballpen' from dual union
select 3, 'a ball' from dual union
select 4, 'ball pen' from dual union
select 5, 'littlefoot' from dual;
var v varchar2(10);
exec :v := 'ball';
select *
from t
where val like '%' || :v || '%'
order by case
when val = :v then 1
when regexp_like ( val, '(^|\s|\W)' || :v || '($|\s|\W)' ) then 2
else 3
end, id;
ID VAL
0 ball
3 a ball
4 ball pen
1 basketball
2 ballpen
Oracle 文本
如果在列上创建 Oracle Text 索引,则可以使用 contains 来查找匹配的行。调用两次。一次找到完全匹配。然后再次显示与单词的匹配。
然后按照分数从高到低排序。先是准确分数,再是其他:
create index test_i on t ( val ) indextype is ctxsys.context;
select t.*, score (1), score (2) from t
where contains ( val, :v, 1 ) > 0
or contains ( val, '%' || :v || '%', 2 ) > 0
order by case
when val = :v then 1
else 2
end, score ( 1 ) desc, score ( 2 ) desc;
ID VAL SCORE(1) SCORE(2)
0 ball 4 4
3 a ball 4 4
4 ball pen 4 4
1 basketball 0 4
2 ballpen 0 4