【问题标题】:SQL Server 2008 - Case / If statements in SELECT Clause [duplicate]SQL Server 2008 - SELECT 子句中的 Case / If 语句 [重复]
【发布时间】: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 }

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

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案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 与适当值不匹配的语句。

          【讨论】:

            猜你喜欢
            • 2013-12-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-12-05
            • 2021-08-09
            • 1970-01-01
            相关资源
            最近更新 更多