Bezdepbonusu7Программирование: статьи и ответы

Вопрос

SQL Server 2008 - операторы Case / If в предложении SELECT

Автор вопроса: Tejaswi YerukalapudiОтветов: 6

У меня есть запрос, который должен работать вот так -


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
}

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

sqlsql-servertsql

Ответы

Ответ 1 · рейтинг 19 · Remus Rusanu

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

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

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

Ответ 2 · рейтинг 22 · Sam Saffron

Вы ищете оператор 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 · рейтинг 9 · Jeffrey Hantin

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

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

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

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

Ответ 4 · рейтинг 2 · Sutirth

Простое выражение 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 · Rob Boek

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 · Joel Mansford

Наиболее очевидные решения уже перечислены. В зависимости от того, где находится запрос (то есть в коде приложения), вы не всегда можете использовать операторы 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 не соответствует подходящему значению, не затрагивая механизм хранения.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы