这是关于在MS SQL中使用SELECT CASE的两种方法的问题[CASE WHEN X = Y]和[CASE X WHEN Y]
我正在尝试根据其值为字段定义存储桶。我需要使用范围,所以有必要使用“<”或“>”标识符
作为一个简单的例子,我知道它的工作原理如下:
SELECT CASE WHEN x < 0 THEN 'a' WHEN X > 100 THEN 'b' ELSE 'c' END
现在我必须编写很多这些,会有超过3个桶,字段名称很长,所以这很难保持清洁和易于遵循。我希望使用select命令的另一种方式,但对我而言,我似乎只能使用equals:
SELECT CASE X WHEN 0 then 'y' ELSE 'z' END
但是如何使用此表单来指定范围条件,如上所述?类似的东西:
SELECT CASE X WHEN < 0 THEN 'a' WHEN > 100 THEN 'b' ELSE "c" END
这个不起作用。
谢谢!
答案 0 :(得分:3)
作为一种替代方法,请记住,可以对作为“简单”CASE语句输入的值进行数学运算。我经常为此目的使用ROUND,如下所示:
SELECT
CASE ROUND(X, -2, 1)
WHEN 0 THEN 'b' -- 0-99
WHEN 100 THEN 'c' -- 100-199
ELSE 'a' -- 200+
END
由于您的示例包含正开放范围和负开放范围,因此这种方法可能对您无效。
还有另一种方法:如果你只考虑SELECT语句中的可读性,你可以编写一个标量值函数来隐藏所有的混乱:
CREATE FUNCTION dbo.ufn_SortValuesIntoBuckets (@inputValue INT) RETURNS VARCHAR(10) AS
BEGIN
DECLARE @outputValue VARCHAR(10);
SELECT @outputValue =
CASE WHEN @inputValue < 0 THEN 'a'
WHEN @inputValue BETWEEN 0 AND 100 THEN 'b'
WHEN @inputValue > 100 THEN 'c'
END;
RETURN @outputValue;
END;
GO
所以现在你的SELECT语句就是:
SELECT dbo.ufn_SortValuesIntoBuckets(X);
最后一个考虑因素:在基准测试期间,我经常发现,“搜索”表单(您试图避免使用)实际上比“简单”表单具有更好的性能,具体取决于您拥有的CASE数量。因此,如果性能是一个考虑因素,那么在你改变太多东西之前做一些基准测试可能是值得的。
答案 1 :(得分:1)
CASE
没有这样的“第三种形式” - 只有搜索且支持简单案例 *
即使您应用条件的变量始终相同,您也需要使用搜索的类型(即具有单独的条件)。
如果您希望在X
表示复杂表达式时避免在SQL中重复,请使用WITH
子句或嵌套查询为您选择的表达式指定名称。
<小时/> * 您的第一个示例的官方名称是“搜索
CASE
表达式”;您的第二个示例称为“简单CASE
表达式”。
答案 2 :(得分:1)
使用BETWEENs看起来不会那么糟糕:
SELECT CASE
WHEN X < 0 THEN 'a'
WHEN X BETWEEN 0 AND 100 THEN 'b'
WHEN X BETWEEN 100 AND 200 THEN 'c'
ELSE 'd' END
答案 3 :(得分:0)
这实际上是一个非常有趣的问题。类似于C# 9.0 relational pattern
SELECT CASE X WHEN < 0 THEN 'a'
WHEN > 100 THEN 'b'
ELSE 'c'
END
C# 9.0
DeliveryTruck t when t.GrossWeightClass switch
{
> 5000 => 10.00m + 5.00m,
< 3000 => 10.00m - 2.00m,
_ => 10.00m,
},
SQL CASE表达式具有两种形式:简单和搜索。
但是SQL标准也定义了 SQL:2003扩展CASE表达式(F262)。主要供应商几乎没有采用此功能。
case — Conditional Expressions by Markus Winand
所谓的扩展格在紧随其后才接受比较运算符,从而解除了简单格总是使用等于(=)比较的限制。以下示例使用小于运算符(<)将值映射到间隔中。它还依赖于when子句的优先级:第一个真实条件获胜。
CASE x WHEN < 0 THEN '< 0'
WHEN < 10 THEN '[0, 10['
WHEN < 100 THEN '[10, 100['
ELSE '>100'
END