SQL IN Wildcard Char

120
14

У меня есть запрос, который использует фильтр IN и работает нормально. Мне интересно, есть ли что-то вроде символа подстановки, который не будет ничего фильтровать

Select * 
FROM [tbl_Leads]
where p_contact_first_name in ('Tom')

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

спросил(а) 2021-01-19T18:06:29+03:00 6 месяцев, 1 неделя назад
1
Решение
100

Оператор IN не позволяет подстановочным знакам или частичным значениям совпадать. На самом деле это просто синтаксический сахар цепочки логических операторов OR.

Этот запрос:

SELECT 1 FROM SomeTable AS T
WHERE T.Column IN (1, 2, 3, 4)

Точно так же, как:

SELECT 1 FROM SomeTable AS T
WHERE
T.Column = 1 OR
T.Column = 2 OR
T.Column = 3 OR
T.COlumn = 4

И именно поэтому наличие значения NULL со списком NOT IN сделает весь логический результат UNKNOWN (следовательно, интерпретируется как false и никогда не будет возвращать какую-либо запись):

SELECT 1 FROM SomeTable AS T
WHERE T.Column NOT IN (1, 2, NULL, 4)

Будет:

SELECT 1 FROM SomeTable AS T
WHERE
NOT(
T.Column = 1 OR
T.Column = 2 OR
T.Column = NULL OR -- Always resolve to UNKNOWN (handled as false for the whole condition)
T.COlumn = 4
)

У вас есть несколько вариантов условного применения фильтра, такого как IN:

    Используйте OR против другого условия:

    DECLARE @ApplyInFilter BIT = 0

    SELECT 1 FROM SomeTable AS T
    WHERE
    (@ApplyInFilter = 1 AND T.Column IN (1, 2, 3, 4)) OR
    @ApplyInFilter = 0

    Избегайте запроса вообще (нужно повторить весь оператор):

    DECLARE @ApplyInFilter BIT = 0

    IF @ApplyInFilter = 1
    BEGIN
    SELECT 1 FROM SomeTable AS T
    WHERE
    T.Column IN (1, 2, 3, 4)
    END
    ELSE
    BEGIN
    SELECT 1 FROM SomeTable AS T
    END

    Используйте динамический SQL, чтобы условно опустить фильтр:

    DECLARE @ApplyInFilter BIT = 0

    DECLARE @DynamicSQL VARCHAR(MAX) = '
    SELECT 1 FROM SomeTable AS T '

    IF @ApplyInFilter = 1
    SET @DynamicSQL += ' WHERE T.Column IN (1, 2, 3, 4) '

    EXEC (@DynamicSQL)

К сожалению, лучший подход, если вы планируете использовать несколько условных фильтров - это динамический SQL. Это будет сложнее всего кодировать, но лучше для производительности (с некоторыми оговорками). Пожалуйста, прочитайте ссылку Джорджа Менутиса, чтобы полностью понять плюсы и минусы каждого подхода.

ответил(а) 2021-01-19T18:06:29+03:00 6 месяцев, 1 неделя назад
45

Как сказал Дейл Баррелл, быстрый способ реализации условий динамического поиска (именно в чем заключается ваша проблема) - это поместить код:

....and field=values or @searchThisField=0

Другим решением будет динамический sql.

Я считаю статью Erland Sommarskog воплощением анализа этой конкретной темы.

ответил(а) 2021-01-19T18:06:29+03:00 6 месяцев, 1 неделя назад
46

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

ответил(а) 2021-01-19T18:06:29+03:00 6 месяцев, 1 неделя назад
45

Вы можете использовать не существует, чтобы получить желаемые результаты. Насколько я понимаю, если у вас есть имя, такое как Том, вам нужна только эта строка, а если нет, вы хотите, чтобы отображались все остальные строки.

 select 1 as ID, 'Tom' as Name into #temp 
union all
select 2 as ID, 'Ben' as Name union all
select 3 as ID, 'Kim' as Name
union all
select 4 as ID, 'Jim' as Name

This query will check if Tom exists then display only that row if not display all.

select * from #temp
where name = 'TOm' or not exists (select 1 from #temp where name = 'Tom')

Result from above query:

ID Name
1 Tom

Давайте проверим это, удалив строку, в которой находится запись Тома.


Delete from #temp 
where name = 'Tom'

Если вы выполните тот же запрос, вы получите следующий результат.

select * from #temp 
where name = 'TOm' or not exists (select 1 from #temp where name = 'Tom')

ID Name
2 Ben
3 Kim
4 Jim

ответил(а) 2021-01-19T18:06:29+03:00 6 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема