Как структурировать запрос с помощью большого, сложного предложения where? - PullRequest
1 голос
/ 30 января 2012

У меня есть запрос SQL, который принимает эти параметры:

@SearchFor  nvarchar(200) = null 
,@SearchInLat Decimal(18,15) = null
,@SearchInLng Decimal(18,15) = null
,@SearchActivity int = null
,@SearchOffers bit = null
,@StartRow int
,@EndRow int

Переменные @SearchFor, @SearchActivity, @SearchOffers могут быть либо нулевыми, либо ненулевыми. @SearchInLat и @SearchInLng должны оба иметь значение NULL или оба имеют значения.

Я не собираюсь публиковать весь запрос как скучный и трудный для чтения, но предложение WHERE имеет такую ​​форму:

( -- filter by activity --
    (@SearchActivity IS NULL)
    OR (@SearchActivity = Activities.ActivityID)
)
AND ( -- filter by Location --
    (@SearchInLat is NULL AND @SearchInLng is NULL)
    OR ( ... )
)
AND ( -- filter by activity --
    @SearchActivity is NULL
    OR ( ... )
)
AND ( -- filter by has offers --
    @SearchOffers is NULL
    OR ( ... )
)
AND (
    ... -- more stuff
)

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

Я вижу два способа сделать это:

  1. Создайте запрос в виде строки в моем клиентском приложении, чтобы предложение WHERE содержало фильтры только для соответствующих параметров. Проблема в том, что это означает отсутствие доступа к базе данных с помощью хранимых процедур, как и все остальное на данный момент.
  2. Измените хранимую процедуру так, чтобы она проверяла, какие аргументы имеют значение null, и выполняет дочерние процедуры в зависимости от того, каким аргументам она передана. Проблема здесь в том, что это будет означать многократное повторение в определении процедур и, следовательно, будет труднее поддерживать.

Что мне делать? Или мне просто продолжать, как я сейчас делаю? У меня установлено OPTION (RECOMPILE) для процедур, но я слышал, что это не работает прямо в Server 2005. Кроме того, я планирую добавить больше параметров в этот процесс, поэтому я хочу убедиться, что любое решение, которое у меня есть, является справедливым масштабируемая.

Ответы [ 3 ]

4 голосов
/ 30 января 2012

Ответ заключается в использовании DynamicSQL (будь то в клиенте или в SP, использующем sp_executesql), но причина в том, что он длинный, поэтому вот ссылка ...

DynamicУсловия поиска в T-SQL

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

1 голос
/ 30 января 2012

Возможно, альтернативой может быть выполнение нескольких отдельных операторов выбора?

, например

( -- filter by activity --
if @SearchActivity is not null
    insert into tmpTable (<columns>)
    select *
    from myTable
    where (@SearchActivity = Activities.ActivityID)
)

( -- filter by Location --
if @SearchInLat is not null and @SearchInLng is not null
    insert into tmpTable (<columns>)
    select *
    from myTable
    where (latCol = @SearchInLat AND lngCol = @SearchInLng)

и т.д ...

затем выберите временную таблицу для возврата окончательного набора результатов.

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

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

0 голосов
/ 31 января 2012

Сначала посмотрите на представление, как говорили другие.

Если возможно, вы можете использовать предложения IF, чтобы упростить запросы на основе предоставленных параметров.

Вы также можете использовать функции или представления для инкапсуляции некоторого кода, если вы обнаружите, что часто повторяете его.

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