在 SQL Server 中执行嵌套 case 语句逻辑的最佳方法

Posted

技术标签:

【中文标题】在 SQL Server 中执行嵌套 case 语句逻辑的最佳方法【英文标题】:Best way to do nested case statement logic in SQL Server 【发布时间】:2010-10-05 01:55:18 【问题描述】:

我正在编写一个 SQL 查询,其中返回的一些列需要根据相当多的条件进行计算。

我目前正在使用嵌套的 case 语句,但它变得很乱。有没有更好(更有条理和/或可读性)的方式?

(我使用的是 Microsoft SQL Server,2005)


一个简化的例子:

SELECT
    col1,
    col2,
    col3,
    CASE
        WHEN condition 
        THEN
            CASE
                WHEN condition1 
                THEN
                    CASE 
                        WHEN condition2
                        THEN calculation1
                        ELSE calculation2
                    END
                ELSE
                    CASE 
                        WHEN condition2
                        THEN calculation3
                        ELSE calculation4
                    END
            END
        ELSE 
            CASE 
                WHEN condition1 
                THEN 
                    CASE
                        WHEN condition2 
                        THEN calculation5
                        ELSE calculation6
                    END
                ELSE
                    CASE
                        WHEN condition2 
                        THEN calculation7
                        ELSE calculation8
                    END
            END            
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

【问题讨论】:

您好,您是否使用工具(如 SQLinForm)很好地缩进嵌套查询? 感谢您教我一个更好的嵌套CASE WHEN的格式化方法 在某些时候这肯定是有效和有用的,但总的来说,我喜欢让逻辑远离我的 SQL 查询。只是给后代的提示。 【参考方案1】:

用户定义的函数可能会更好地服务,至少隐藏逻辑 - 尤其是。如果您需要在多个查询中执行此操作

【讨论】:

【参考方案2】:

您可以尝试某种 COALESCE 技巧,例如:

选择合并( CASE WHEN 条件 1 THEN 计算 1 ELSE NULL END, CASE WHEN 条件 2 THEN 计算 2 ELSE NULL END, 等等... )

【讨论】:

很好,我刚刚测试了它以确保它短路,并惊讶地发现它确实如此。因此,如果条件 1 检查是否被零除,那么在条件 2 中执行它似乎是安全的。不确定这是否得到保证。 一个问题是,如果您的一个案例合法地想要返回 NULL,那么它就不再可能了。 这是一个很棒的技巧,但请记住,它的性能可能不如单独使用 CASE 语句。这在此处的“社区添加”部分“记录” - msdn.microsoft.com/en-us/library/ms190349.aspx。当我实施这个解决方案时,我的 DBA 只是放下了锤子...... 什么时候比一个案例陈述更好(@beach 的回答)? 如何重命名此答案中的列。例如,如果我想将“calculation1”重命名为“CAL1”...从语法上讲怎么可能?【参考方案3】:

我个人就是这样做的,保持嵌入的 CASE 表达式受到限制。我也会让 cmets 解释发生了什么。如果太复杂,就分解成函数。

SELECT
    col1,
    col2,
    col3,
    CASE WHEN condition THEN
      CASE WHEN condition1 THEN
        CASE WHEN condition2 THEN calculation1
        ELSE calculation2 END
      ELSE
        CASE WHEN condition2 THEN calculation3
        ELSE calculation4 END
      END
    ELSE CASE WHEN condition1 THEN 
      CASE WHEN condition2 THEN calculation5
      ELSE calculation6 END
    ELSE CASE WHEN condition2 THEN calculation7
         ELSE calculation8 END
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

【讨论】:

【参考方案4】:

下面是嵌套“复杂”案例语句的简单解决方案: --嵌套案例复杂表达式

select  datediff(dd,Invdate,'2009/01/31')+1 as DaysOld, 
    case when datediff(dd,Invdate,'2009/01/31')+1 >150 then 6 else
        case when datediff(dd,Invdate,'2009/01/31')+1 >120 then 5 else 
            case when datediff(dd,Invdate,'2009/01/31')+1 >90 then 4 else 
                case when datediff(dd,Invdate,'2009/01/31')+1 >60 then 3 else 
                    case when datediff(dd,Invdate,'2009/01/31')+1 >30 then 2 else 
                        case when datediff(dd,Invdate,'2009/01/31')+1 >30 then 1 end 
                    end
                end
            end
        end
    end as Bucket
from rm20090131atb

只要确保每个 case 语句都有一个结束语句

【讨论】:

如果您希望他人阅读您的答案,您可能需要对其进行格式化。 这对原始问题中使用的方法有何改进?【参考方案5】:

将所有这些案例合二为一。


SELECT
    col1,
    col2,
    col3,
    CASE
        WHEN condition1 THEN calculation1 
        WHEN condition2 THEN calculation2
        WHEN condition3 THEN calculation3
        WHEN condition4 THEN calculation4
        WHEN condition5 THEN calculation5
        ELSE NULL         
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

【讨论】:

【参考方案6】:

你可以结合多个条件来避免这种情况:

CASE WHEN condition1 = true AND condition2 = true THEN calculation1 
     WHEN condition1 = true AND condition2 = false 
     ELSE 'what so ever' END,

【讨论】:

【参考方案7】:

我们可以将多个条件组合在一起以减少性能开销。

让我们想要执行案例的三个变量 a b c 。我们可以这样做:

CASE WHEN a = 1 AND b = 1 AND c = 1 THEN '1'
     WHEN a = 0 AND b = 0 AND c = 1 THEN '0'
ELSE '0' END,

【讨论】:

【参考方案8】:

我经历了这个,发现所有答案都超级酷,但是想添加到@deejers 给出的答案

    SELECT
    col1,
    col2,
    col3,
    CASE
        WHEN condition1 THEN calculation1 
        WHEN condition2 THEN calculation2
        WHEN condition3 THEN calculation3
        WHEN condition4 THEN calculation4
        WHEN condition5 THEN calculation5         
    END AS 'calculatedcol1',
    col4,
    col5 -- etc
FROM table

您可以将 ELSE 设为可选,因为它不是强制性的,它在许多情况下都非常有用。

【讨论】:

【参考方案9】:

这个例子可能对你有所帮助,图片展示了当有 if 和多个内部 if 循环时 SQL case 语句的样子

【讨论】:

请放代码文本而不是截图,因为截图很难重复使用或确认。

以上是关于在 SQL Server 中执行嵌套 case 语句逻辑的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

Sql server 未在查询中使用嵌套 case 语句更新记录

SQL Server 2008 使用 case 语句查看错误

SQL Case 语句子选择内的子选择分组

SQL Server判断语句(IF ELSE/CASE WHEN )

SQL 查询执行时间、SQL Server、嵌套查询

具有嵌套 CASES 的 Sql 标量值函数