SQL Server 2008 - SELECT 子句中的 Case / If 语句 [重复]

Posted

技术标签:

【中文标题】SQL Server 2008 - SELECT 子句中的 Case / If 语句 [重复]【英文标题】:SQL Server 2008 - Case / If statements in SELECT Clause [duplicate] 【发布时间】:2010-11-10 11:44:09 【问题描述】:

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

如果(变量 = xyz) 选择 col1,col2 否则 IF(var = zyx) 选择 col2,col3 别的 选择 col7,col8 从 . . .

如何在不为每个子句编写单独查询的情况下在 T-SQL 中实现这一点?目前我正在运行它

如果 (var = xyz) 查询1 否则 IF (var = zyx) 查询2 别的 查询3

这只是根据值选择不同列的大量冗余代码。 有其他选择吗?

【问题讨论】:

【参考方案1】:

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

【讨论】:

看来我是忍者了! :) 我仍然是一个 n00b,所以我可能(很容易)错了,但我认为这实际上并不能回答问题,对吧? OP 询问他如何选择 multiple 列,而不是将值的几个选项之一分配给单个列,这似乎(以及几个答案)正在这样做。如果我是 OP,那么@JoelMansford 的答案似乎是最正确的。如果我错了,请告诉我/为什么我错了!【参考方案2】:

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

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

当然,这取决于您的数据模型的实际架构和确切的查询,但这只是一个提示,因此您不会将过程编程的命令式思维思维框架带入 SQL 的声明式世界。

【讨论】:

+1 非常好的观察【参考方案3】:

试试类似的东西

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

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

或者,您可以构建某种动态 SQL hack 来共享查询尾部;我以前用 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 与适当值不匹配的语句。

【讨论】:

以上是关于SQL Server 2008 - SELECT 子句中的 Case / If 语句 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Sql Server 2008 获取用于插入到 select 中的 scope_identity 列表?

SQL 超级重点 (SQL Server 2008)

学习Microsoft SQL Server 2008技术内幕:T-SQL语法基础--第4章

检测重叠日期并更新最新记录SQL Server 2008

SQL SERVER2008里面sql语句删除临时表失败

SQL Server2008R2学习记录