Объедините 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 превращает столбец в одну ячейку, содержащую строку регулярного выражения.

Я действительно понимаю, что это, вероятно, убийца производительности, но, к счастью, я не настолько обеспокоен производительностью в этот момент

Другие вопросы по тегам