2009-07-08 2 views
1

Это несколько продолжение к Slow Exists Check. Предложение Alex работает и успешно избегает повторения кода, но я все еще получаю вторую проблему. Рассмотрим пример ниже (от Алекса Кузнецова). В нем у меня есть две ветви, чтобы обрабатывать 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 

ответ

0
Select blah from foo  
Where (@inpo1 is null or @inpo1 = inpo1) 
and (@inpo2 is null or @inpo2 = inpo2) 

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

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

+0

Как я упоминал в книге Slow Exists, это медленное решение. – Brian

0

Вот пример. Измените инструкции 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

Я пробовал это раньше (упоминается в начальном вопросе). Это медленно. – Brian

0

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

+0

Я думал об этом как о решении, но считаю, что это что-то использовать, если у меня нет выбора, а не идеала. – Brian

1

В таких случаях я использую sp_executesql, как описано в статье Erland в: Using sp_executesql Всякий раз, когда динамический SQL используется, отсутствующие разрешения могут быть проблемы, поэтому у меня есть реальный счет сети для модульного тестирования, я добавить эту учетную запись к фактической роли , и я выдаю себя за эту реальную учетную запись всякий раз, когда я тестирую динамический SQL, как описано здесь: Database Unit Testing: Impersonation

+0

Да, это то, что я в конечном итоге использовал. – Brian