仅使用 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】:一种可能的方法是在子查询中结合使用EXISTS
和LIKE
:
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”子句,如何仅重新训练第一个数据集的列?
服务器上的 Where In 子句错误仅支持最多 2100 个参数