если еще в CTE?

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

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

Но я получаю ошибку на этом. Действительно ли возможно еще иметь если в CTEs? Если не там работа вокруг Или лучший подход.

Спасибо.

9
задан Scott W 13 July 2010 в 17:04
поделиться

3 ответа

попробуйте:

;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) возьмет этот код (где нельзя использовать индекс с этим беспорядком ИЛИ 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

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

22
ответ дан 4 December 2019 в 08:14
поделиться

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

Другим способом может быть UNION ALL с пунктами WHERE, как предлагали другие. UNION ALL заменит IF ELSE

1
ответ дан 4 December 2019 в 08:14
поделиться

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

Ваш лучший подход по этой и многим другим причинам - вытащить IF за пределы оператора:

if(condition true)
    select * from table_A
else
    select * from table_B
3
ответ дан 4 December 2019 в 08:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: