Подтвердить что ты не робот

SQL Server 2008 - Операторы case/If в разделе SELECT

У меня есть запрос, который должен запускаться следующим образом:

If(var = xyz) 
   SELECT col1, col2
ELSE IF(var = zyx)
   SELECT col2, col3
ELSE
   SELECT col7,col8

FROM 

.
.
.

Как добиться этого в T-SQL без написания отдельных запросов для каждого предложения? В настоящее время я запускаю его как

IF (var = xyz) {
  Query1
}
ELSE IF (var = zyx) {
  Query2
}
ELSE {
  Query3
}

Это просто избыточный код для выбора разных столбцов в зависимости от значения. Любые альтернативы?

4b9b3361

Ответ 1

Просто обратите внимание, что на самом деле вам может быть лучше иметь 3 отдельных SELECTS для оптимизации. Если у вас есть один SELECT, тогда сгенерированный план должен будет проецировать все столбцы col1, col2, col3, col7, col8 и т.д., Хотя, в зависимости от значения времени выполнения @var, нужны только некоторые из них. Это может привести к планам, которые делают ненужные кластерные поисковые запросы, поскольку некластеризованный индекс не охватывает все столбцы, спроецированные SELECT.

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

Конечно, это зависит от фактической схемы вашей модели данных и точных запросов, но это всего лишь хэдз-ап, поэтому вы не привносите концептуальное мышление в процессуальное программирование в декларативный мир SQL.

Ответ 2

Вы ищете инструкцию CASE

http://msdn.microsoft.com/en-us/library/ms181765.aspx

Пример, скопированный из MSDN:

USE AdventureWorks;
GO
SELECT   ProductNumber, Category =
      CASE ProductLine
         WHEN 'R' THEN 'Road'
         WHEN 'M' THEN 'Mountain'
         WHEN 'T' THEN 'Touring'
         WHEN 'S' THEN 'Other sale items'
         ELSE 'Not for sale'
      END,
   Name
FROM Production.Product
ORDER BY ProductNumber;
GO

Ответ 3

Попробуйте что-нибудь вроде

SELECT
    CASE var
        WHEN xyz THEN col1
        WHEN zyx THEN col2
        ELSE col7
    END AS col1,
    ...

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

В качестве альтернативы вы можете создать какой-то динамический SQL-хак, чтобы разделить хвост запроса; Я сделал это с iBatis раньше.

Ответ 4

Простое выражение CASE:

CASE input_expression 
     WHEN when_expression THEN result_expression [ ...n ] 
     [ ELSE else_result_expression ] 
END

Искаженное выражение CASE:

CASE
     WHEN Boolean_expression THEN result_expression [ ...n ] 
     [ ELSE else_result_expression ] 
END

Ссылка: http://msdn.microsoft.com/en-us/library/ms181765.aspx

Ответ 5

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

Пример:

SELECT
    CASE @var
        WHEN 'xyz' THEN col1
        WHEN 'zyx' THEN col2
        ELSE col7
    END,
    CASE @var
        WHEN 'xyz' THEN col2
        WHEN 'zyx' THEN col3
        ELSE col8
    END
FROM Table
...

Ответ 6

Наиболее очевидные решения уже перечислены. В зависимости от того, где выполняется запрос (например, в коде приложения), вы не всегда можете использовать операторы IF, а встроенные операторы CASE могут становиться болезненными, когда количество столбцов становится условным. Предполагая, что Col1 + Col3 + Col7 являются одним и тем же типом, а также Col2, Col4 + Col8, вы можете сделать это:

SELECT Col1, Col2 FROM tbl WHERE @Var LIKE 'xyz'
UNION ALL
SELECT Col3, Col4 FROM tbl WHERE @Var LIKE 'zyx'
UNION ALL
SELECT Col7, Col8 FROM tbl WHERE @Var NOT LIKE 'xyz' AND @Var NOT LIKE 'zyx'

Поскольку это единственная команда, есть несколько преимуществ производительности в отношении кэширования плана. Также оптимизатор запросов быстро устранит те утверждения, где @Var не соответствует соответствующему значению, не касаясь механизма хранения.