Сочетание LIKE с IN в SQL

Вместо выполнения:

ВЫБЕРИТЕ a
ИЗ b
ГДЕ НРАВИТСЯ 'a%'
ИЛИ НРАВИТСЯ 'b%'
ИЛИ НРАВИТСЯ ' c%'


есть ли способ выполнить что-то вроде этого псевдокода?

SELECT a
FROM b
ГДЕ a IN ('a%', 'b%', 'c%')


person JonathanWolfson    schedule 19.06.2009    source источник
comment
Могу я спросить, что не так с первым синтаксисом, которого вы хотели бы избежать?   -  person JohnFx    schedule 19.06.2009
comment
Потому что это включает в себя много избыточного ввода и введения логических операторов, и когда я смотрю на что-то, содержащее множество круглых скобок и операций ИЛИ, это менее удобоваримо.   -  person JonathanWolfson    schedule 23.06.2009


Ответы (6)


Возможно, это слишком специфично для вашего примера, но вы можете сделать LIKE '[a-c]%'. Кроме этого, я не знаю о каком-либо синтаксисе, подобном LIKE IN.

person n8wrl    schedule 19.06.2009
comment
Вы также можете использовать '[abce]%', если хотите пропустить букву (в этом примере d) - person Nathan Koop; 20.06.2009
comment
если список для оператора IN является результатом запроса, то как это сделать? - person siri; 11.10.2011

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

SELECT b.a FROM b INNER JOIN #likevals on b.a LIKE #likevals.value + '%'

ГДЕ #likevals выглядит так:

value
------
a
b
c
person C-Pound Guru    schedule 19.06.2009
comment
В качестве альтернативы подстановочный знак может отображаться в значениях таблицы «temp», чтобы обеспечить большую гибкость. - person onedaywhen; 25.11.2011

Вы могли бы использовать

SELECT a
FROM b
WHERE a >= 'A'
AND a < 'D'

что обеспечит вам наилучшее использование индекса на a.

Бьюсь об заклад, другой ответ даст вам сканирование индекса или сканирование таблицы.

person dkretz    schedule 19.06.2009
comment
Я понятия не имею, что ты мог бы сделать это. Спасибо. Я думаю, вы хотели бы разместить комментарий в коде, я мог видеть, что люди неправильно понимают этот пункт. - person Nathan Koop; 20.06.2009

Только что заметил это. Есть много способов решить эту проблему, но вот один гибкий метод, который вы можете использовать с решениями для создания отчетов. Просто в прошлом мне давали ту же проблему для решения, и я никогда не передавал проблему ;o). Заранее извиняюсь, если это не анализируется - закинул и возился с памятью, но вы должны получить идею

CREATE FUNCTION fn_PatList (@PatList VARCHAR(200))
RETURNS @SearchList TABLE (Pattern VARCHAR(100))
AS 
BEGIN
 WHILE @PatList LIKE '%,%'
 BEGIN
  SELECT @PatList = LTRIM(RTRIM(@PatList))
  INSERT INTO @SearchList
   SELECT RTRIM(LEFT(@PatList,PATINDEX('%,%',@PatList)-1))
  SELECT @PatList = SUBSTRING(@PatListmPATINDEX('%,%',@PatList)+1, 8000)
 END
 INSERT INTO @SearchList 
  SELECT LTRIM(RTRIM(@PatList))
 RETURN
END

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

Теперь..

SELECT Names.Person
FROM Names
INNER JOIN Fn_PatList ('Fred%,John%') PatList
ON Names.Person LIKE PatList.Pattern

Возможно, вы захотите разрешить пробелы, т.е. пробелы между запятыми и другим мусором. Короче говоря, теперь вы можете использовать свою функцию для обработки списков шаблонов. Надеюсь, это удовлетворит ваши требования - с ним довольно легко работать. Возможно, вы также захотите рассмотреть индексацию, но вы можете выбрать ее оттуда.

person Simon Hughes    schedule 05.04.2012

Нет. Оператор IN ожидает фактические значения. Самое близкое, что вы могли бы получить, это что-то вроде:

Select a
from b 
where a in (
    select a 
    from b
    WHERE a LIKE 'a%'
    OR a LIKE 'b%'
    OR a LIKE 'c%')

За исключением того, что это просто дублирует ваши усилия для этого конкретного случая, поэтому я бы не стал использовать приведенный выше код. По сути, вам нужно передать фактические значения в оператор IN. Вывод здесь заключается в том, что вы можете использовать оператор select внутри оператора IN для получения ваших значений.

Кроме того, я исхожу из предположения, что вы не пытаетесь выбрать буквальные значения «a», «b», «c» и т. д., и что эти значения представляют собой какую-то другую строку, которую вы не хотите нам показывать. .

person Doug R    schedule 19.06.2009

У меня была такая же проблема, мне пришлось написать сценарий для нее. (Если это все еще в ваших мыслях)

вот что я в итоге использовал:

 DECLARE @User INT, @MaskCount INT
     SET @User = 1
     Select @MaskCount = COUNT(*) from BI.dbo.ALL_Access_Masks

     WHILE (@User <= @MaskCount)
        Begin

        DECLARE @ProntoUserID Nvarchar (12)
        Set @ProntoUserID = (select Distinct [USER_ID] from BI.dbo.ALL_Access_Masks where [ID] = @User)

        DECLARE @DB Nvarchar (3)
        Set @DB = (select Distinct DB_Code from BI.dbo.ALL_Access_Masks where [ID] = @User)


        DECLARE @TopFlag INT
        SET @TopFlag = 1

            Drop Table #UserMasks 
            Drop Table #UserMasks1 

            Create Table #UserMasks
            ([RN] [Int] NOT NULL,
            [DB] [Nvarchar] (3) NOT NULL,
            [Mask] [Nvarchar](10) NOT NULL)

            Create Table #UserMasks1
            ([DB] [Nvarchar] (3) NOT NULL,
            [Mask] [Nvarchar](10) NOT NULL)

            Insert Into #UserMasks1 

                select @DB ,PD_Mk_1  from BI.dbo.ALL_Access_Masks where [ID] = @User and PD_Mk_1 is not NULL
                Union All select @DB ,PD_Mk_2  from BI.dbo.ALL_Access_Masks where [ID] = @User and PD_Mk_2  is not null and DB_Code = @DB
                Union All select @DB ,PD_Mk_3  from BI.dbo.ALL_Access_Masks where [ID] = @User and PD_Mk_3  is not null and DB_Code = @DB
                Union All select @DB ,PD_Mk_4  from BI.dbo.ALL_Access_Masks where [ID] = @User and PD_Mk_4  is not null and DB_Code = @DB
                Union All select @DB ,PD_Mk_5  from BI.dbo.ALL_Access_Masks where [ID] = @User and PD_Mk_5  is not null and DB_Code = @DB
                Union All select @DB ,PD_Mk_6  from BI.dbo.ALL_Access_Masks where [ID] = @User and PD_Mk_6  is not null and DB_Code = @DB
                Union All select @DB ,PD_Mk_7  from BI.dbo.ALL_Access_Masks where [ID] = @User and PD_Mk_7  is not null and DB_Code = @DB
                Union All select @DB ,PD_Mk_8  from BI.dbo.ALL_Access_Masks where [ID] = @User and PD_Mk_8  is not null and DB_Code = @DB
                Union All select @DB ,PD_Mk_9  from BI.dbo.ALL_Access_Masks where [ID] = @User and PD_Mk_9  is not null and DB_Code = @DB
                Union All select @DB ,PD_Mk_10 from BI.dbo.ALL_Access_Masks where [ID] = @User and PD_Mk_10 is not null and DB_Code = @DB


            Insert Into #UserMasks

                Select ROW_NUMBER() OVER ( PARTITION BY @DB ORDER BY Mask DESC) AS RN,DB,Mask from #UserMasks1
                where DB = @DB


        WHILE (@TopFlag <=(select COUNT(*) from #UserMasks))

                        BEGIN

                            Insert Into BI.dbo.Masked_Users
                            select @DB,@ProntoUserID,'PD' as 'Mask_Type',Code
                            from BI.dbo.Mask_Lookup M
                            where code like (select Mask + '%' from #UserMasks Where RN = @TopFlag)
                            and [Database] = @DB and M.Mask = 'PD'

        SET @TopFlag = @TopFlag + 1

                    End

        SET @User = @User + 1

End

GO
person Tim    schedule 25.11.2011
comment
Ваш ответ пришел после принятого ответа и кажется гораздо более сложным способом решения той же проблемы. Есть ли преимущество у вашего ответа перед принятым? - person Ryan Gates; 06.11.2012