Есть ли в SQL комбинация "LIKE" и "IN"? - PullRequest
302 голосов
/ 10 июня 2010

В SQL мне (к сожалению) часто приходится использовать условия "LIKE" из-за баз данных, которые нарушают почти все правила нормализации.Я не могу изменить это прямо сейчас.Но это не имеет отношения к вопросу.

Кроме того, я часто использую условия типа WHERE something in (1,1,2,3,5,8,13,21) для лучшей читаемости и гибкости моих операторов SQL.

Есть ли какой-либо возможный способ объединить эти две вещи безписать сложные подвыборы?

Я хочу что-то столь же простое, как WHERE something LIKE ('bla%', '%foo%', 'batz%') вместо этого:

WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'

Я работаю здесь с SQl Server и Oracle, но мне интересно, еслиэто возможно в любой СУБД.

Ответы [ 23 ]

180 голосов
/ 10 июня 2010

В SQL нет комбинации LIKE & IN, а тем более в TSQL (SQL Server) или PLSQL (Oracle).Одной из причин этого является то, что полнотекстовый поиск (FTS) является рекомендуемой альтернативой.

И реализации Oracle, и SQL Server FTS поддерживают ключевое слово CONTAINS, но синтаксис все же немного отличается:

Oracle:

WHERE CONTAINS(t.something, 'bla OR foo OR batz', 1) > 0

SQL Server:

WHERE CONTAINS(t.something, '"bla*" OR "foo*" OR "batz*"')

Ссылка:

55 голосов
/ 10 июня 2010

Если вы хотите, чтобы ваше утверждение было легко читаемым, вы можете использовать REGEXP_LIKE (доступно начиная с версии Oracle 10).

Пример таблицы:

SQL> create table mytable (something)
  2  as
  3  select 'blabla' from dual union all
  4  select 'notbla' from dual union all
  5  select 'ofooof' from dual union all
  6  select 'ofofof' from dual union all
  7  select 'batzzz' from dual
  8  /

Table created.

Исходный синтаксис:

SQL> select something
  2    from mytable
  3   where something like 'bla%'
  4      or something like '%foo%'
  5      or something like 'batz%'
  6  /

SOMETH
------
blabla
ofooof
batzzz

3 rows selected.

И простой запрос с REGEXP_LIKE

SQL> select something
  2    from mytable
  3   where regexp_like (something,'^bla|foo|^batz')
  4  /

SOMETH
------
blabla
ofooof
batzzz

3 rows selected.

НО ...

Я бы не рекомендовал его сам из-зане очень хорошая производительность.Я бы придерживался нескольких предикатов LIKE.Так что примеры были просто для удовольствия.

46 голосов
/ 10 июня 2010

вы застряли с

WHERE something LIKE 'bla%'
OR something LIKE '%foo%'
OR something LIKE 'batz%'

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

FROM YourTable                y
    INNER JOIN YourTempTable  t On y.something LIKE t.something

попробуйте (используя синтаксис SQL Server):

declare @x table (x varchar(10))
declare @y table (y varchar(10))

insert @x values ('abcdefg')
insert @x values ('abc')
insert @x values ('mnop')

insert @y values ('%abc%')
insert @y values ('%b%')

select distinct *
FROM @x x
WHERE x.x LIKE '%abc%' 
   or x.x LIKE '%b%'


select distinct x.*  
FROM @x             x
    INNER JOIN  @y  y On x.x LIKE y.y

ВЫВОД:

x
----------
abcdefg
abc

(2 row(s) affected)

x
----------
abc
abcdefg

(2 row(s) affected)
18 голосов
/ 21 апреля 2011

В PostgreSQL есть форма ANY или ALL:

WHERE col LIKE ANY( subselect )

или

WHERE col LIKE ALL( subselect )

, где подвыбор возвращает ровно один столбец данных.

12 голосов
/ 18 октября 2016

Другое решение, должно работать на любой СУБД:

WHERE EXISTS (SELECT 1
                FROM (SELECT 'bla%' pattern FROM dual UNION ALL
                      SELECT '%foo%'        FROM dual UNION ALL
                      SELECT 'batz%'        FROM dual)
               WHERE something LIKE pattern)
10 голосов
/ 10 июня 2010

Я бы предложил использовать пользовательскую функцию TableValue, если вы хотите инкапсулировать методы Inner Join или Temp Table, показанные выше.Это позволило бы ему читать немного яснее.

После использования функции разделения, определенной в: http://www.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx

, мы можем написать следующее на основе созданной мной таблицы под названием «Рыба» (int id, varchar (50) Name)

SELECT Fish.* from Fish 
    JOIN dbo.Split('%ass,%e%',',') as Splits 
    on Name like Splits.items  //items is the name of the output column from the split function.

Выходы

1   Bass
2   Pike
7   Angler
8   Walleye
7 голосов
/ 10 июня 2010

Вместо этого используйте внутреннее соединение:

SELECT ...
FROM SomeTable
JOIN
(SELECT 'bla%' AS Pattern 
UNION ALL SELECT '%foo%'
UNION ALL SELECT 'batz%'
UNION ALL SELECT 'abc'
) AS Patterns
ON SomeTable.SomeColumn LIKE Patterns.Pattern
7 голосов
/ 10 июня 2010

Один из подходов состоит в том, чтобы сохранить условия во временной таблице (или табличной переменной в SQL Server) и присоединиться к ней следующим образом:

SELECT t.SomeField
FROM YourTable t
   JOIN #TempTableWithConditions c ON t.something LIKE c.ConditionValue
4 голосов
/ 23 апреля 2015

вы даже можете попробовать это

Функция

CREATE  FUNCTION [dbo].[fn_Split](@text varchar(8000), @delimiter varchar(20))
RETURNS @Strings TABLE
(   
  position int IDENTITY PRIMARY KEY,
  value varchar(8000)  
)
AS
BEGIN

DECLARE @index int
SET @index = -1

WHILE (LEN(@text) > 0)
  BEGIN 
    SET @index = CHARINDEX(@delimiter , @text) 
    IF (@index = 0) AND (LEN(@text) > 0) 
      BEGIN  
        INSERT INTO @Strings VALUES (@text)
          BREAK 
      END 
    IF (@index > 1) 
      BEGIN  
        INSERT INTO @Strings VALUES (LEFT(@text, @index - 1))  
        SET @text = RIGHT(@text, (LEN(@text) - @index)) 
      END 
    ELSE
      SET @text = RIGHT(@text, (LEN(@text) - @index))
    END
  RETURN
END

Запрос

select * from my_table inner join (select value from fn_split('ABC,MOP',','))
as split_table on my_table.column_name like '%'+split_table.value+'%';
3 голосов
/ 19 февраля 2016

Мне тоже хотелось что-то подобное. Я только что проверил, используя комбинацию SUBSTRING и IN, и это эффективное решение для такого рода проблем. Попробуйте следующий запрос:

Select * from TB_YOUR T1 Where SUBSTRING(T1.Something, 1,3) IN ('bla', 'foo', 'batz')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...