если еще в CTE? - PullRequest
       17

если еще в CTE?

8 голосов
/ 25 мая 2010

Я хочу выполнить оператор выбора в CTE на основе кодировки. что-то вроде ниже

;with CTE_AorB
(
  if(condition)
    select * from table_A
   else
    select * from table_B
),
CTE_C as
(
   select * from CTE_AorB // processing is removed
)

Но я получаю сообщение об ошибке. Возможно ли иметь что-то еще внутри CTE? Если нет, то есть ли обходной путь или лучший подход.

Спасибо.

Ответы [ 4 ]

22 голосов
/ 25 мая 2010

попробовать:

;with CTE_AorB
(
    select * from table_A WHERE (condition true)
    union all
    select * from table_B WHERE NOT (condition true)
),
CTE_C as
(
   select * from CTE_AorB // processing is removed
)

ключ к условию динамического поиска - убедиться, что индекс используется. Вот очень полная статья о том, как обращаться с этой темой:

Условия динамического поиска в T-SQL Эрланда Соммарского

охватывает все проблемы и методы попыток написания запросов с несколькими необязательными условиями поиска. Это главное, что вам нужно беспокоиться, это не дублирование кода, а использование индекса. Если ваш запрос не может использовать индекс, он будет плохо сформирован. Существует несколько методов, которые могут использоваться или не разрешать использование индекса.

вот оглавление:

  Introduction
      The Case Study: Searching Orders
      The Northgale Database
   Dynamic SQL
      Introduction
      Using sp_executesql
      Using the CLR
      Using EXEC()
      When Caching Is Not Really What You Want
   Static SQL
      Introduction
      x = @x OR @x IS NULL
      Using IF statements
      Umachandar's Bag of Tricks
      Using Temp Tables
      x = @x AND @x IS NOT NULL
      Handling Complex Conditions
   Hybrid Solutions – Using both Static and Dynamic SQL
      Using Views
      Using Inline Table Functions
   Conclusion
   Feedback and Acknowledgements
   Revision History

если вы работаете с верной версией SQL Server 2008, можно использовать дополнительную технику, см .: Условия динамического поиска в версии T-SQL для SQL 2008 (SP1 CU5 и более поздние версии)

Если вы используете правильную версию SQL Server 2008, вы можете просто добавить OPTION (RECOMPILE) к запросу, и значение локальной переменной во время выполнения используется для оптимизации.

Учтите, что OPTION (RECOMPILE) примет этот код (где индекс не может использоваться с этим беспорядком OR s):

WHERE
    (@search1 IS NULL or Column1=@Search1)
    AND (@search2 IS NULL or Column2=@Search2)
    AND (@search3 IS NULL or Column3=@Search3)

и оптимизировать его во время выполнения (при условии, что только @ Search2 был передан со значением):

WHERE
    Column2=@Search2

и можно использовать индекс (если он определен в столбце 2)

3 голосов
/ 25 мая 2010

Никогда не пытайтесь помещать такие условия, как IF, в отдельные операторы запроса. Даже если вам удастся справиться с этим, это единственный верный способ снизить производительность. Помните, что одно утверждение означает один план, и план должен быть сгенерирован таким образом, чтобы удовлетворить оба случая, когда условие истинно и когда условие ложно, сразу, Это обычно приводит к худшему возможному плану, так как «условие» обычно создает взаимоисключающий путь доступа к плану и объединение двух результатов всегда при сквозном сканировании таблицы.

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

if(condition true)
    select * from table_A
else
    select * from table_B
1 голос
/ 25 мая 2010

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

Другим способом было бы ОБЪЕДИНИТЬ ВСЕ с предложениями WHERE, как это предлагалось другими UNION ALL заменит IF ELSE

0 голосов
/ 22 января 2015

Если вы используете параметр, тогда вам нужен только один оператор.

@ID (Some parameter)

;with CTE
(
    select * from table_A WHERE id = @ID
    union all
    select * from table_B WHERE (id = @ID and condition)
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...