Использование SQL LIKE и IN вместе - PullRequest
42 голосов
/ 23 февраля 2010

Есть ли способ использовать LIKE и IN вместе?

Я хочу добиться чего-то подобного.

SELECT * FROM tablename WHERE column IN ('M510%', 'M615%', 'M515%', 'M612%');

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

Ответы [ 10 ]

54 голосов
/ 23 февраля 2010

Как насчет использования подстроки с IN.

select * from tablename where substring(column,1,4) IN ('M510','M615','M515','M612')
51 голосов
/ 23 февраля 2010

Вы можете сделать это одним запросом, соединив отдельные LIKE с ИЛИ:

SELECT * FROM tablename
WHERE column LIKE 'M510%'
OR    column LIKE 'M615%'
OR    column LIKE 'M515%'
OR    column LIKE 'M612%';

Просто помните, что такие вещи, как LIKE и функции для каждой строки, не всегда хорошо масштабируются. Если ваша таблица, вероятно, станет большой, вы можете захотите рассмотреть возможность добавления еще одного столбца в вашу таблицу для независимого хранения первых четырех символов поля.

Это дублирует данные, но вы можете гарантировать их постоянство, используя триггеры вставки и обновления. Затем поместите индекс в этот новый столбец, и ваши запросы станут такими:

SELECT * FROM tablename WHERE newcolumn IN ('M510','M615','M515','M612');

Это перемещает стоимость расчета в точку, где это необходимо (когда данные изменяются), , а не каждый раз, когда вы ее читаете. На самом деле, вы можете пойти еще дальше и получить новый столбец в виде логического значения, указывающего, что это был один из четырех специальных типов (если эта группа специальных значений будет меняться нечасто). Тогда запрос будет еще быстрее:

SELECT * FROM tablename WHERE is_special = 1;

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

8 голосов
/ 23 февраля 2010

Вам нужно будет использовать несколько LIKE терминов, соединенных OR.

5 голосов
/ 23 февраля 2010

Используйте более длинную версию IN, которая является связкой ИЛИ.

SELECT * FROM tablename 
WHERE column LIKE 'M510%'
OR column LIKE 'M615%'
OR column LIKE 'M515%'
OR column LIKE 'M612%';
2 голосов
/ 11 февраля 2013
SELECT * FROM tablename
  WHERE column IN 
    (select column from  tablename 
    where column like 'M510%' 
    or column like 'M615%' 
    OR column like 'M515%' 
    or column like'M612%'
    )
2 голосов
/ 28 ноября 2012
substr([column name],
       [desired starting position (numeric)],
       [# characters to include (numeric)]) in ([complete as usual])

Пример

substr([column name],1,4) in ('M510','M615', 'M515', 'M612')
1 голос
/ 28 января 2016

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

Функция

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('M510', 'M615', 'M515', 'M612',','))
as split_table on my_table.column_name like '%'+split_table.value+'%';
1 голос
/ 07 сентября 2012

Вы можете использовать подзапрос с подстановочными знаками:

 SELECT 'Valid Expression'
 WHERE 'Source Column' LIKE (SELECT '%Column' --FROM TABLE)

Или вы можете использовать одну строку:

 SELECT 'Valid Expression'
 WHERE 'Source Column' LIKE ('%Source%' + '%Column%')
1 голос
/ 07 июля 2012

Я пробовал другой способ

скажем, в таблице есть значения

<code>
    1   M510
    2   M615
    3   M515
    4   M612
    5   M510MM
    6   M615NN
    7   M515OO
    8   M612PP
    9   A
    10  B
    11  C
    12  D

Здесь столбцы с 1 по 8 действительны, а остальные недействительны

<code>
  SELECT COL_VAL
    FROM SO_LIKE_TABLE SLT
   WHERE (SELECT DECODE(SUM(CASE
                              WHEN INSTR(SLT.COL_VAL, COLUMN_VALUE) > 0 THEN
                               1
                              ELSE
                               0
                            END),
                        0,
                        'FALSE',
                        'TRUE')
            FROM TABLE(SYS.DBMS_DEBUG_VC2COLl('M510', 'M615', 'M515', 'M612'))) =
         'TRUE'

Я использовал функцию INSTR, и я попытался выяснить, совпадает ли значение в таблице с любым из значений в качестве входных данных. Если это так, он вернет свой индекс, то есть больше нуля. В случае, если значение таблицы не совпадает ни с одним из входных данных, он вернет НОЛЬ. Этот индекс я добавил, чтобы указать успешное совпадение.

Кажется, он работает.

Надеюсь, это поможет.

0 голосов
/ 11 августа 2015

Для совершенно динамичного решения это достижимо, комбинируя курсор и временную таблицу.С этим решением вам не нужно знать ни начальную позицию, ни длину, и его можно расширять без добавления каких-либо OR в ваш запрос SQL.

В этом примере, скажем, вы хотите выбрать идентификатор,Детали и дата создания из таблицы, в которой определенный текст находится внутри «Подробности».

Сначала создайте таблицу FilterTable со строками поиска в столбце под названием Поиск.

В качестве источника вопросазапрошено:

insert into [DATABASE].dbo.FilterTable
select 'M510' union
select 'M615' union
select 'M515' union 
select 'M612'

Затем вы можете отфильтровать ваши данные следующим образом:

DECLARE @DATA NVARCHAR(MAX)

CREATE TABLE #Result (ID uniqueIdentifier, Details nvarchar(MAX), Created datetime)

DECLARE DataCursor CURSOR local forward_only FOR  
SELECT '%' + Search + '%'
FROM [DATABASE].dbo.FilterTable

OPEN DataCursor   
FETCH NEXT FROM DataCursor INTO @DATA   

WHILE @@FETCH_STATUS = 0   
BEGIN   

    insert into #Result
        select ID, Details, Created
        from [DATABASE].dbo.Table (nolock)
        where Details like @DATA

   FETCH NEXT FROM DataCursor INTO @DATA   
END   

CLOSE DataCursor   
DEALLOCATE DataCursor 

select * from #Result
drop table #Result

Надеюсь, это помогло

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...