Эффективная обработка нескольких необязательных ограничений в предложении Where - PullRequest
1 голос
/ 09 июля 2009

Это что-то вроде продолжения Slow Exists Check . Предложение Алекса работает и успешно избегает повторения кода, но у меня все еще остается вторая проблема. Рассмотрим пример ниже (от Алекса Кузнецова). В нем у меня есть две ветви, чтобы справиться с 1 противопоказанием. Если бы у меня было 2 необязательных ограничения, я бы получил 4 ветви. В основном, количество ветвей увеличивается экспоненциально с количеством ограничений.

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

Может кто-нибудь предложить предложения о том, как добавить больше ограничений, не добавляя много операторов if?

Примечание: Ранее я пробовал просто соединить x is null or inpo = @inpo вместе, но это очень медленно. Имейте в виду, что хотя тест inpo = @inpo может быть обработан с помощью некоторого рода индексирования черной магии, тест на недействительность в конечном итоге будет оцениваться для каждой строки в таблице.

IF @inpo IS NULL BEGIN
  SELECT a,b,c 
    FROM dbo.ReuseMyQuery(@i1)
    ORDER BY c;
END ELSE BEGIN
  SELECT a,b,c 
    FROM dbo.ReuseMyQuery(@i1)
    WHERE inpo = @inpo
    ORDER BY c;
END

Вариант два: 2 ограничения:

IF @inpo IS NULL BEGIN      
    IF @inpo2 IS NULL BEGIN
        SELECT a,b,c 
        FROM dbo.ReuseMyQuery(@i1)
        ORDER BY c;
    END ELSE BEGIN
        SELECT a,b,c 
        FROM dbo.ReuseMyQuery(@i1)
        WHERE inpo2 = @inpo2
        ORDER BY c;
    END
END ELSE BEGIN
    IF @inpo2 IS NULL BEGIN
        SELECT a,b,c 
        FROM dbo.ReuseMyQuery(@i1)
        WHERE inpo = @inpo
        ORDER BY c;
    END ELSE BEGIN
        SELECT a,b,c 
        FROM dbo.ReuseMyQuery(@i1)
        WHERE inpo = @inpo AND
              inpo2 = @inpo2
        ORDER BY c;
    END
END

Ответы [ 5 ]

5 голосов
/ 09 июля 2009

это лучший справочник: http://www.sommarskog.se/dyn-search-2005.html

1 голос
/ 09 июля 2009

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

0 голосов
/ 09 июля 2009

Я понимаю, что ваш вопрос может быть чисто академическим, но если у вас есть реальные случаи использования, вы рассматривали возможность предоставления только оптимизированных запросов для наиболее распространенных сценариев?

0 голосов
/ 09 июля 2009

Вот грубый пример. Измените операторы LIKE в предложении WHERE в зависимости от того, хотите ли вы «начинается с» или «содержит» или точное совпадение в вашем запросе.

CREATE PROCEDURE dbo.test
@name       AS VARCHAR(50) = NULL,
@address1       AS VARCHAR(50) = NULL,
@address2       AS VARCHAR(50) = NULL,
@city       AS VARCHAR(50) = NULL,
@state      AS VARCHAR(50) = NULL,
@zip_code       AS VARCHAR(50) = NULL
AS

BEGIN

SELECT  [name],
            address1,
            address2,
            city,
            state,
            zip_code
FROM    my_table
WHERE   ([name] LIKE @name + '%' OR @name IS NULL)
            AND (address1 LIKE @address1 + '%' OR @address1 IS NULL)
            AND (address2 LIKE @address2 + '%' OR @address2 IS NULL)
            AND (city LIKE @city + '%' OR @city IS NULL)
            AND (state LIKE @state + '%' OR @state IS NULL)
            AND (zip_code LIKE @zip_code + '%' OR @zip_code IS NULL)
ORDER BY    [name]
END
GO
0 голосов
/ 09 июля 2009
Select blah from foo    
Where (@inpo1 is null or @inpo1 = inpo1)
and (@inpo2 is null or @inpo2 = inpo2)

Видимо, это слишком медленно. Интересно.

Рассматривали ли вы генерацию кода? Длинные запросы с большим количеством дубликатов являются проблемой, только если они должны поддерживаться напрямую.

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