Как дополнительно применить предложение WHERE IN на основе переменной? - PullRequest
0 голосов
/ 09 марта 2019

У меня есть хранимая процедура, которую необходимо отфильтровать по списку идентификаторов, которые передаются в виде списка с разделителями-запятыми (т. Е. '1,2,3').

Я хочу применить предложение WHERE IN, которое будетсопоставлять эти идентификаторы, но ТОЛЬКО если переменная содержит что-либо (IS NOT NULL AND <> '').

Вот упрощенная проблема: http://sqlfiddle.com/#!18/5f6be/1

В настоящее время она работает для одного и нескольких идентификаторов.Но при прохождении '' или NULL он должен вернуть все, но ничего не возвращает.

CTEs и нумерация страниц существуют по причине, пожалуйста, предоставьте решение, которое этого не меняет.

Ответы [ 3 ]

5 голосов
/ 09 марта 2019

Используя DelimitedSplit8k_lead, вы можете достичь этого, выполнив:

CREATE PROC YourProc @List varchar(8000) = NULL AS
BEGIN

    SELECT {YourColumns}
    FROM YourTable YT
         OUTER APPLY dbo.DelimitedSplit8k_Lead(@List,',') DS
    WHERE DS.item = YT.YourColumn
       OR NULLIF(@List,'') IS NULL
    OPTION (RECOMPILE);
END

Используется OUTER APPLY, как будто передано NULL, набор данных не будет удален. RECOMPILE есть, так как он превращается в «Catch-all query» с добавлением обработки NULL.

3 голосов
/ 09 марта 2019

Почему бы не использовать JOIN вместо подзапроса в предложении WHERE.

set @userIds = nullif(ltrim(@userIds),'')
select u.*
from Users u
left join string_split(@userIds,',') s on u.Id=s.value
where s.value is not null or @userIds is null
1 голос
/ 09 марта 2019

Старый школьный метод:

WHERE
(@userIds IS NULL OR @userIds = '' OR U.Id IN (SELECT * FROM STRING_SPLIT(@userIds, ',')))

Добавьте в конце OPTION (RECOMPILE), чтобы это сработало и обрезало план.


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

WHERE U.Id IN
(
   SELECT * FROM STRING_SPLIT(@userIds, ',')
   UNION ALL
   SELECT U.Id WHERE NULLIF(@userIds, '') IS NULL
)
...