2016-02-10 5 views
3

Я знаю, что этот вопрос задан, но у меня есть немного другой вкус. Я использую случай, когда единственное, что у меня есть, - это предложение WHERE запроса, и у меня есть 2 таблицы.Комбинировать LIKE и IN, используя только предложение WHERE

Используя простой пример:

Table1 содержит 1 столбец с именем «FULLNAME» с сотнями значений
Table2 содержит 1 столбец с именем «ОБРАЗЕЦ» с некоторым соответствием текстом

так, что мне нужно сделать, это выбрать все значения из таблицы 1, которые соответствуют значениям в таблице 2.

Вот простой пример:

Table1 (FULLNAME)
ANTARCTICA
ANGOLA
АВСТРАЛИЯ
АФРИКА
INDIA
ИНДОНЕЗИЯ

Table2 (ОБРАЗЕЦ)

В

эффективно то, что мне нужно, это запись в Table1, которые содержат значение из таблицы 2 (результатом будет ANTARCTICA, ANGOLA, INDIA, INDONESIA)

Другими словами, то, что мне нужно что-то вроде:

Select * от Table1 где FULLNAME В LIKE (выберите '%' || Шаблон || «%» От Table2)

Коварным здесь у меня только контроль над где положение, я не могу контролировать Выбрать пункт на всех или добавить присоединяется, поскольку я использую продукт, который позволяет только контроль над предложением where. Я также не могу использовать хранимые процедуры.

Возможно ли это?

Я использую Oracle в качестве серверной БД

Благодаря

+0

являются модели всегда два символа, и сделать вы хотите только совпадение в начале (как в ваших примерах) или где-нибудь (как «содержит» и подсказывает использование вами подстановочных знаков)? –

ответ

3

Один из возможных подходов заключается в использовании EXISTS в сочетании с LIKE в подзапрос:

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

Это великолепно, спасибо! – NullPointer

2

Я считаю, что вы можете сделать это с помощью простого JOIN:

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

DISTINCT есть для тех случаев, когда вы может иметь совпадение с несколькими строками в Table2.

+0

Согласен, однако я не могу использовать JOIN, я должен сделать это, используя предложение where ... Я понял, хотя скоро опубликует ответ – NullPointer

0

Правильно, это связано с небольшим количеством обмана. Концептуально то, что я сделал, превращает столбец из 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 превращает колонку в одну ячейку, содержащую регулярную строку выражения.

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

+0

Какую версию Oracle вы используете? Если 11g или выше, вы можете использовать 'LISTAGG()', а не сумасшедший 'SYS_CONNECT_BY_PATH()'. –

+0

Я нахожусь на 11g, так что да, вы правы. Меня заменит LISTAGG. Thanks – NullPointer

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||'%')