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
}
Это просто избыточный код для выбора разных столбцов в зависимости от значения.
Любые альтернативы?
Ответы
Ответ 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 не соответствует соответствующему значению, не касаясь механизма хранения.