SQL Server 2008 - SELECT子句中的Case / If语句

时间:2009-07-13 22:56:36

标签: sql sql-server tsql

我有一个应该像这样运行的查询 -


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
}

这只是很多冗余代码,只是根据值选择不同的列。 任何替代方案?

6 个答案:

答案 0 :(得分:22)

您正在寻找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

答案 1 :(得分:19)

这里只是注意,出于优化原因,您可能最好有3个单独的SELECTS。如果您只有一个SELECT,那么生成的计划必须投影所有列col1,col2,col3,col7,col8等,但是,根据运行时@var的值,只需要一些。这可能会导致执行不必要的聚簇索引查找的计划,因为非聚集索引不会覆盖SELECT投影的所有列。

另一方面,3个单独的SELECTS,每个投影所需的列只能受益于非聚集索引,在每种情况下仅覆盖您的预计列。

当然这取决于数据模型的实际模式和确切的查询,但这只是一个提升,所以你不要将过程式编程的命令性思维思维框架带到SQL的声明性世界。

答案 2 :(得分:9)

尝试类似

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

换句话说,使用条件表达式选择值,然后重命名列。

或者,您可以构建某种动态SQL hack来共享查询尾部;我以前用iBatis做过这个。

答案 3 :(得分:2)

简单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

答案 4 :(得分:0)

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
...

答案 5 :(得分:0)

已经列出了最明显的解决方案。根据查询的位置(即在应用程序代码中),您不能总是使用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与适当值不匹配但不触及存储引擎的语句。