仅使用 WHERE 子句组合 LIKE 和 IN

Posted

技术标签:

【中文标题】仅使用 WHERE 子句组合 LIKE 和 IN【英文标题】:Combine LIKE and IN using only WHERE clause 【发布时间】:2016-05-21 09:25:09 【问题描述】:

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

使用简单的例子:

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

所以,我需要做的是从表 1 中选择与表 2 中的值匹配的所有值。

这是一个简单的例子:

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

表 2(模式) 安 在

实际上我需要的是表 1 中的条目,其中包含表 2 中的值(结果将是南极洲、安哥拉、印度、印度尼西亚)

换句话说,我需要的是这样的:

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

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

这可能吗?

我使用 Oracle 作为后端数据库

谢谢

【问题讨论】:

模式是否总是两个字符,您只想在开头(如您的示例中)或任何地方(如“包含”和您使用通配符所建议的那样)匹配? 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

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

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

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

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

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

【讨论】:

【参考方案3】:

是的,这涉及到一些诡计。从概念上讲,我所做的是将 PATTERN 中的列转换为单个单元格,并将其与 REGEX_LIKE 一起使用

所以“AN 和 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 中的子查询将列转换为包含正则表达式字符串的单个单元格。

虽然我确实意识到这可能是一个性能杀手,但幸运的是我现在并没有那么在意性能

【讨论】:

您使用的是什么版本的 Oracle?如果 11g 或更高,你可以使用LISTAGG() 而不是疯狂的SYS_CONNECT_BY_PATH() 我在 11g 上,所以是的,你是对的,我将用 LISTAGG 替换它。谢谢【参考方案4】:

我相信你可以通过一个简单的JOIN来做到这一点:

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

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

【讨论】:

同意,但是我不能使用 JOIN,我必须只使用 where 子句来执行此操作...不过我已经想通了,很快就会发布答案

以上是关于仅使用 WHERE 子句组合 LIKE 和 IN的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spark 执行“WHERE IN”子句,如何仅重新训练第一个数据集的列?

7_mysql查询之where子句

LIKE运算符

服务器上的 Where In 子句错误仅支持最多 2100 个参数

Node.JS 仅返回 MySQL“WHERE IN”子句的部分记录

PostgreSQL:使用 LIKE、ANY 和通配符的 Where 子句