仅使用 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||'%')
一种可能的方法是在子查询中结合使用 EXISTS
和 LIKE
:
select * from table1 t1
where exists (select null
from table2 t2
where t1.fullname like '%' || t2.pattern || '%');
我知道有人问过这个问题,但我对它的看法略有不同。我有一个用例,我唯一可以控制的是查询的 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||'%')
一种可能的方法是在子查询中结合使用 EXISTS
和 LIKE
:
select * from table1 t1
where exists (select null
from table2 t2
where t1.fullname like '%' || t2.pattern || '%');