Oracle检查表a列中的字符串是否包含表b列中的单词

时间:2019-02-20 20:36:36

标签: sql oracle oracle11g

在Oracle 11.2.0.4中... 给定具有长varchar列且包含文本段落的表A,我想检查该文本中是否有任何单词存在于具有单个单词的垂直列表的表中。 我正在寻找一种方法来在单个查询中执行此操作,而不是使用游标。

基本上,我认为我需要将段落分成单词,然后加入垂直单词表中,但是在操作上却迷茫了。

Example:
TableA:

+----+--------------------------------------------+
| id |                  comments                  |
+----+--------------------------------------------+
|  1 | This sentence has no reference to any word |
|  2 | But this one references jungle             |
|  3 | And this one references Trees              |
+----+--------------------------------------------+

TableB:

+----+---------+
| id |  word   |
+----+---------+
|  1 | Jungle  |
|  2 | Forest  |
|  3 | Trees   |
|  4 | Animals |
|  5 | River   |
+----+---------+

鉴于这些表,我想要一个SQL查询,该查询将告诉我表A第2行和第3行具有表B中存在的单词。

我已经研究过使用xmltype功能将表拆分成单词,然后将它们像这样连接在一起:

select id, 
(select count(1) from tableb f, xmltable(
  '/r/c/text()'
  passing xmltype('<r><c>'||replace((regexp_replace(comments, '[^a-z][^A-Z]')), ' ', '</c><c>')||'</c></r>')
  columns subs varchar2(4000) path '.'
) s where trim(f.word) = trim(s.subs)) words_found, comments
from tablea
where trim(comments) is not null

但是效果不是很好。它只能在失败之前处理少量注释行。

在此先感谢您,如果能得到答复,我深表歉意。我做了很多检查,却没有找到我想要的东西。

2 个答案:

答案 0 :(得分:1)

由于您仅比较单词,因此不需要拆分它们。您可以在LIKE

中使用JOIN表达式
select a.*, b.* from TableA a  JOIN TableB b  ON 
' ' ||lower(a.comments)|| ' ' like  '% '||lower(b.word)||' %'

REGEXP_LIKE

select a.*, b.* from TableA a  JOIN TableB b  ON 
REGEXP_LIKE(a.comments,'(^|\W)'||b.word||'($|\W)','i');

Demo

答案 1 :(得分:0)

简单的INSTR怎么样?

SQL> with
  2  a (id, comments) as
  3    (select 1, 'This sentence has no reference to any word' from dual union all
  4     select 2, 'But this one references jungle'             from dual union all
  5     select 3, 'And this one references Trees'              from dual union all
  6     select 4, 'Jungle animals swim in a river'             from dual
  7    ),
  8  b (id, word) as
  9    (select 1, 'Jungle' from dual union all
 10     select 2, 'Forest' from dual union all
 11     select 3, 'Trees'  from dual union all
 12     select 4, 'Animals' from dual union all
 13     select 5, 'River'   from dual
 14    )
 15  select a.id, a.comments, b.word
 16  from a cross join b
 17  where instr(lower(a.comments), lower(b.word)) > 0
 18  order by a.id, b.word;

        ID COMMENTS                                   WORD
---------- ------------------------------------------ -------
         2 But this one references jungle             Jungle
         3 And this one references Trees              Trees
         4 Jungle animals swim in a river             Animals
         4 Jungle animals swim in a river             Jungle
         4 Jungle animals swim in a river             River

SQL>