在 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 语句查看错误