Oracle Regex匹配忽略顺序的所有单词

时间:2014-03-11 10:18:26

标签: regex oracle

我需要查找匹配所有查询短语但忽略其发生顺序的记录。

例如,我的查询字符串是apple banana kiwi。以下值应该是真的。

  • I like apple, banana and kiwi
  • Banana, kiwi and apple are fruits

以下值应为false

  • He does not like kiwi

如何在Oracle 11中通过SQL实现?

2 个答案:

答案 0 :(得分:2)

在现代正则表达式引擎中,您可以使用前瞻断言将这三个条件合并为一个表达式:

(?:.*?\bapple\b)(?:.*?\bbanana\b)(?:.*?\bkiwi\b)
但是,Oracle不支持预见,这意味着您无法编写同时检查所有三个条件的表达式(*)

您的选择:

  • 拆分正则表达式并将多个简单表达式与AND组合在一起 - 这是最慢的变体,但它可以正常工作。
  • 转储正则表达式并对LIKE使用多个AND子句 - 这会比正则表达式快一点,但相比之下表达复杂性有限。
  • 在该表上设置全文索引并使用它 - 这将是最快的变体,但与正则表达式相比,表达式复杂性有限。但是,对于纯自然语言关键字搜索来说,它就足够了,并且它将支持词干和替代词形式。

(*)从技术上讲,在学术上,你可以。您可以编写一个表达式来检查关键字的所有可能排列,例如

A.*?B.*?C|B.*?C.*?A|C.*?A.*?B|...and so on|and so forth

想想你是否会称这是一个可接受的解决方案。哦,是的,它也会很慢。

答案 1 :(得分:2)

这是一次尝试:

with w as -- The words
(
  select 'apple banana kiwi' words from dual
),
p as -- the patterns taken from the words
(
  select regexp_substr(w.words, '\w+', 1, level) pattern
  from w
  connect by regexp_substr(w.words, '\w+', 1, level) is not null
),
r as -- the phrases to test
(
  select 'I like apple, banana and kiwi' phrase from dual
  union all
  select 'Banana, kiwi and apple are fruits' phrase from dual
  union all
  select 'He does not like kiwi' phrase from dual
)
select r.phrase
       case sum(case instr(upper(r.phrase), upper(p.pattern))
                when 0 then 0
                else 1 end)
       when regexp_count(w.words, '\w+', 1) then 'true'
       else 'false' end all_present
from r, p, w
group by r.phrase, w.words
;

结果:

He does not like kiwi               false
Banana, kiwi and apple are fruits   true
I like apple, banana and kiwi       true

原则:

  • 测试每个模式是否在短语中(instr:如果为0,则不存在,否则为
  • 逐句总结此匹配
  • 如果此总和等于测试的字数(此处为3),则为真