仅使用 WHERE 子句组合 LIKE 和 IN

Combine LIKE and IN using only WHERE clause

我知道有人问过这个问题,但我对它的看法略有不同。我有一个用例,我唯一可以控制的是查询的 WHERE 子句,我有 2 tables.

使用简单的例子:

Table1 包含 1 个名为 "FULLNAME" 的列,其中包含数百个值
Table2 包含 1 个名为 "PATTERN" 的列以及一些匹配的文本

所以,我需要做的是 select Table 1 中与 table 2.

中的值相匹配的所有值

这是一个简单的例子:

Table1(全名)
南极洲
安哥拉
澳大利亚
非洲
印度
印度尼西亚

Table2(模式)


实际上我需要的是 Table1 中的条目,其中包含来自 Table2 的值(结果将是 ANTARCTICA、ANGOLA、INDIA、INDONESIA)

换句话说,我需要的是:

Select * from Table1 where FULLNAME IN LIKE (Select '%' || Pattern || '%' from Table2)

这里棘手的是我只能控制 where 子句,我根本无法控制 Select 子句或添加连接,因为我使用的产品只允许控制 where条款。我也不会使用存储过程。

这可能吗?

我使用 Oracle 作为后端数据库

谢谢

我相信你可以用一个简单的方法做到这一点 JOIN:

SELECT DISTINCT
    fullname
FROM
    Table1 T1
INNER JOIN Table2 T2 ON T1.fullname LIKE '%' || T2.pattern || '%'

DISTINCT 适用于可能与 Table2 中的多行匹配的情况。

对,这涉及到一些技巧。从概念上讲,我所做的是将列从 PATTERN 变成一个单元格,并将其与 REGEX_LIKE

一起使用

所以值 "AN and IN" 变成一个单一的值 '(AN|IN)' - 我只是把它提供给 regexp_like

SELECT FULLNAME from table1  where  
regexp_like(FULLNAME,(SELECT '(' || SUBSTR (SYS_CONNECT_BY_PATH (FULLNAME  , '|'), 2) || ')' Table2
          FROM (SELECT FULLNAME , ROW_NUMBER () OVER (ORDER BY FULLNAME) rn,
                       COUNT (*) OVER () cnt
                  FROM Table2)
         WHERE rn = cnt START WITH rn = 1 CONNECT BY rn = PRIOR rn + 1))

regexp_like 中的子查询将列变成包含正则表达式字符串的单个单元格。

我确实意识到这可能是一个性能杀手,但谢天谢地,我现在并没有那么在意性能

如果模式总是两个字符并且只需要匹配全名的开头,就像您展示的示例一样,您可以这样做:

Select * from Table1 where substr(FULLNAME, 1, 2) IN (Select Pattern from Table2)

这会阻止使用 Table1 上的任何索引,您的实际情况可能需要更灵活...

或者可能效率更低,类似于 TomH 的方法,但是在 inside 中加入一个子查询:

Select * from Table1 where FULLNAME IN (
  Select t1.FULLNAME from Table1 t1
  Join Table2 t2 on t1.FULLNAME like '%'||t2.Pattern||'%')

一种可能的方法是在子查询中结合使用 EXISTSLIKE

select * from table1 t1 
where exists (select null 
              from table2 t2 
              where t1.fullname like '%' || t2.pattern || '%');