Объедините LIKE и IN, используя только предложение WHERE
Я знаю, что этот вопрос был задан, но у меня немного другой вкус. У меня есть случай использования, когда единственное, что я контролирую, это предложение WHERE запроса, и у меня есть 2 таблицы.
Используя простой пример:
Таблица 1 содержит 1 столбец с именем "FULLNAME" с сотнями значений
Таблица 2 содержит 1 столбец с именем "PATTERN" с некоторым соответствующим текстом
Итак, что мне нужно сделать, это выбрать все значения из таблицы 1, которые соответствуют значениям в таблице 2.
Вот простой пример:
Таблица 1 (ФИО)
ANTARCTICA
ANGOLA
АВСТРАЛИЯ
АФРИКА
ИНДИЯ
ИНДОНЕЗИЯ
Таблица2 (ШАБЛОН)
В
По сути, мне нужны записи в Таблице 1, которые содержат значения из Таблицы 2 (результатом будет ANTARCTICA, ANGOLA, INDIA, INDONESIA)
Другими словами, мне нужно что-то вроде:
Выберите * из таблицы 1, где FULLNAME IN LIKE (выберите "%" || Pattern || "%" из таблицы 2)
Сложность в том, что у меня есть только контроль над предложением where, я вообще не могу управлять предложением Select или добавлять объединения, так как использую продукт, который позволяет контролировать только предложение where. Я также не могу использовать хранимые процедуры.
Это возможно?
Я использую Oracle в качестве внутренней базы данных
Спасибо
4 ответа
Одним из возможных подходов является использование EXISTS
в комбинации с LIKE
в подзапросе:
select * from table1 t1
where exists (select null
from table2 t2
where t1.fullname like '%' || t2.pattern || '%');
Если шаблоны всегда состоят из двух символов и должны соответствовать только началу полного имени, как в приведенных вами примерах, вы можете сделать следующее:
Select * from Table1 where substr(FULLNAME, 1, 2) IN (Select Pattern from Table2)
Что предотвращает использование какого-либо индекса в Таблице 1, и ваш реальный случай, возможно, должен быть более гибким...
Или, возможно, даже менее эффективно, аналогично подходу TomH, но с объединением внутри подзапроса:
Select * from Table1 where FULLNAME IN (
Select t1.FULLNAME from Table1 t1
Join Table2 t2 on t1.FULLNAME like '%'||t2.Pattern||'%')
Я считаю, что вы можете сделать это с помощью простого JOIN
:
SELECT DISTINCT
fullname
FROM
Table1 T1
INNER JOIN Table2 T2 ON T1.fullname LIKE '%' || T2.pattern || '%'
DISTINCT
есть ли в тех случаях, когда вы можете иметь совпадение с несколькими строками в Table2
,
Да, это было немного обманом. Концептуально то, что я сделал, это превратил столбец из 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 превращает столбец в одну ячейку, содержащую строку регулярного выражения.
Я действительно понимаю, что это, вероятно, убийца производительности, но, к счастью, я не настолько обеспокоен производительностью в этот момент