Вместо выполнения:
ВЫБЕРИТЕ a
ИЗ b
ГДЕ НРАВИТСЯ 'a%'
ИЛИ НРАВИТСЯ 'b%'
ИЛИ НРАВИТСЯ ' c%'
есть ли способ выполнить что-то вроде этого псевдокода?
SELECT a
FROM b
ГДЕ a IN ('a%', 'b%', 'c%')
Сочетание LIKE с IN в SQL
Ответы (6)
Возможно, это слишком специфично для вашего примера, но вы можете сделать LIKE '[a-c]%'. Кроме этого, я не знаю о каком-либо синтаксисе, подобном LIKE IN.
Вы можете сбросить значения критериев во временную таблицу (без подстановочного знака). Затем выполните соединение, например:
SELECT b.a FROM b INNER JOIN #likevals on b.a LIKE #likevals.value + '%'
ГДЕ #likevals выглядит так:
value
------
a
b
c
Вы могли бы использовать
SELECT a
FROM b
WHERE a >= 'A'
AND a < 'D'
что обеспечит вам наилучшее использование индекса на a.
Бьюсь об заклад, другой ответ даст вам сканирование индекса или сканирование таблицы.
Только что заметил это. Есть много способов решить эту проблему, но вот один гибкий метод, который вы можете использовать с решениями для создания отчетов. Просто в прошлом мне давали ту же проблему для решения, и я никогда не передавал проблему ;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
Возможно, вы захотите разрешить пробелы, т.е. пробелы между запятыми и другим мусором. Короче говоря, теперь вы можете использовать свою функцию для обработки списков шаблонов. Надеюсь, это удовлетворит ваши требования - с ним довольно легко работать. Возможно, вы также захотите рассмотреть индексацию, но вы можете выбрать ее оттуда.
Нет. Оператор 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» и т. д., и что эти значения представляют собой какую-то другую строку, которую вы не хотите нам показывать. .
У меня была такая же проблема, мне пришлось написать сценарий для нее. (Если это все еще в ваших мыслях)
вот что я в итоге использовал:
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