Использование LIKE в предложении Oracle IN - PullRequest
16 голосов
/ 20 мая 2011

Я знаю, что могу написать запрос, который будет возвращать все строки, которые содержат любое количество значений в данном столбце, например:

Select * from tbl where my_col in (val1, val2, val3,... valn)

, но если, например, val1, может появиться где угоднов my_col, который имеет тип данных varchar (300), я мог бы вместо этого написать:

select * from tbl where my_col LIKE '%val1%'

Есть ли способ объединения этих двух методов.Мне нужно найти около 30 возможных значений, которые могут появиться в любом месте текста в свободной форме столбца.

Объединение этих двух утверждений следующими способами не работает:

select * from tbl where my_col LIKE ('%val1%', '%val2%', 'val3%',....) 

select * from tbl where my_col in ('%val1%', '%val2%', 'val3%',....)

Ответы [ 8 ]

27 голосов
/ 20 мая 2011
select * from tbl 
where my_col like '%val1%' or my_col like'%val2%' or my_col like '%val3%', ...

Но будьте осторожны, это может быть довольно медленно ... В качестве альтернативы, вы можете вставить все допустимые значения (включая знаки %) в таблицу и частично соединить эту таблицу:

select * from tbl
where exists (select 1 from all_likes where tbl.my_col like all_likes.value)

Для истинного полнотекстового поиска вы можете посмотреть на Oracle Text:

http://www.oracle.com/technetwork/database/enterprise-edition/index-098492.html

6 голосов
/ 20 мая 2011

Нет, вы не можете этого сделать.Значения в предложении IN должны быть точными совпадениями.Вы можете изменить выбор следующим образом:

SELECT *
  FROM tbl
 WHERE my_col LIKE %val1%
    OR my_col LIKE %val2%
    OR my_col LIKE %val3%
 ...

Если val1, val2, val3 ... достаточно похожи, вы можете использовать регулярные выражения в операторе REGEXP_LIKE.

4 голосов
/ 26 сентября 2015

A REGEXP_LIKE будет выполнять поиск регулярного выражения без учета регистра.

select * from Users where Regexp_Like (User_Name, 'karl|anders|leif','i')

Это будет выполнено как полное сканирование таблицы - так же, как решение LIKE or, поэтомупроизводительность будет действительно плохой, если таблица не маленькая.Если он вообще не используется часто, он может быть в порядке.

Если вам нужна какая-то производительность, вам понадобится Oracle Text (или некоторый внешний индексатор).

Для индексирования подстроки с помощью Oracle Text вам понадобится индекс CONTEXT.Это немного связано с тем, что оно предназначено для индексации больших документов и текста с использованием большого количества смартов.Если у вас есть особые потребности, такие как поиск подстрок в числах и во всех словах (включая «the», «a», «a», пробелы и т. Д.), Вам нужно создать пользовательские лексеры, чтобы удалить некоторые умные вещи ...

Если вы вставите много данных, Oracle Text не сделает все быстрее, особенно если вам нужно, чтобы индекс обновлялся внутри транзакций, а не периодически.

1 голос
/ 01 ноября 2018

Это довольно быстро:

select * from listofvalue l 
inner join tbl on tbl.mycol like '%' || l.value || '%'
1 голос
/ 15 марта 2018

Я предпочитаю это

WHERE CASE WHEN my_col LIKE '%val1%' THEN 1    
           WHEN my_col LIKE '%val2%' THEN 1
           WHEN my_col LIKE '%val3%' THEN 1
           ELSE 0
           END = 1

Я не говорю, что это оптимально, но это работает, и это легко понять.Большинство моих запросов используются adhoc один раз, поэтому производительность, как правило, для меня не проблема.

1 голос
/ 13 марта 2018

Просто добавьте ответ @Lukas Eder.

Улучшение, позволяющее избежать создания таблиц и вставки значений (мы могли бы использовать select from dual и unpivot для достижения того же результата "на лету"):

with all_likes as  
(select * from 
    (select '%val1%' like_1, '%val2%' like_2, '%val3%' like_3, '%val4%' as like_4, '%val5%' as like_5 from dual)
    unpivot (
     united_columns for subquery_column in ("LIKE_1", "LIKE_2", "LIKE_3", "LIKE_4", "LIKE_5"))
  )
    select * from tbl
    where exists (select 1 from all_likes where tbl.my_col like all_likes.united_columns)
1 голос
/ 19 декабря 2016

Да, вы можете использовать этот запрос:

  SELECT * FROM RandomTable rt 
    WHERE EXISTS (select 1 from table(sys.dbms_debug_vc2coll(//INSERT STRINGS SEPARATED BY COMMA HERE)) as MemoryTable mt where rt.name like mt.column_value);

Почему мой запрос лучше принятого ответа: вам не нужно разрешение CREATE TABLE для его выполнения. Это может быть выполнено только с разрешениями SELECT.

0 голосов
/ 26 сентября 2015
select * from tbl
 where exists (select 1 from all_likes where all_likes.value = substr(tbl.my_col,0, length(tbl.my_col)))
...