Shorthand 有附加条件的案例

Shorthand CASE with additional conditions

直到今天,我仍然认为 shorthand CASE 不接受附加条件,如

CASE evaluate_this
WHEN TRUE AND another_field ... THEN ...

永远行不通。

今天,当我分心编写一些代码时,我违反了这条规则,只是为了意识到一个 CASE 表达式仍然按预期工作,而另一个则没有。 假设数据如下:

id boolean_one boolean_two field_one field_two
1 TRUE TRUE NULL 'a'
2 TRUE FALSE 2 'a'
3 FALSE TRUE 8 NULL
4 FALSE FALSE NULL NULL

没用的是这样的:

CASE boolean_one
  WHEN TRUE AND field_one IS NOT NULL THEN field_one * UNIFORM(1, 10, RANDOM())
  ELSE field_one
END AS new_field_one

这个想法是,在大多数情况下,new_field_one 的值应该匹配 field_one,唯一的例外是 boolean_one = TRUE AND field_one IS NOT NULL,在这种情况下,它应该被分配 [=] 的乘积50=] 和一个随机整数。

根据上述

,低于 new_field_one 的期望值和实际值
id desired actual
1 NULL NULL
2 20 20
3 8 8
4 NULL 5

所以它在 boolean_one = FALSE AND field_one IS NULL 时也应用随机化。 将表达式固定为

CASE
  WHEN boolean_one = TRUE AND field_one IS NOT NULL THEN...

问题已解决。我发现更有趣、更令人困惑的是,第二个表达式仍然按照它的意思去做:

CASE boolean_two
  WHEN TRUE AND field_two = 'b' THEN 'a'
  WHEN TRUE AND field_two = 'a' THEN 'b'
  ELSE field_two
END AS new_field_two

在这种情况下意味着 new_field_two = 'b' 对于带有 ID = 1 的行,所有其他保持等于 field_two。

所以,这似乎不是向 shorthand CASE 本身添加额外条件的问题,我想这一定与以下事实有关第二个条件是 NULL 检查。我在正确的轨道上吗?

使用快捷语法,“when 表达式”作为一个整体进行评估,然后将该值与“case 表达式”进行比较。它没有将值匹配为 true 然后 运行 额外检查

实际上,您的 true and 基本上被忽略了,因为 true and X 仅等同于布尔逻辑中的 X。然后就是测试boolean_one是否匹配field_one的non-null状态。第二行和第四行对应于 true = truefalse = false,这是您看到的随机结果值。

如果对易读性有真正的好处,您当然可以嵌套 case

case boolean_one
    when true then
        case field_one is not null ... end
    else field_one
end

shawnt00回答的不错,

我喜欢把这两种形式想成

链式 If 表达式

CASE
   WHEN check1 THEN r1
   WHEN check2 THEN r2
   WHEN check3 THEN r3
END

如果与

相同
IF(check1) 
   r1
ELSE IF (check2)
   r2
...

where-as这个“快捷方式”版本是Switch语句形式:

CASE expression
   WHEN val1 THEN r1
   WHEN val2 THEN r2
   WHEN val3 THEN r2
END

相同
SWITCH(expression){
    CASE val1: r1
    CASE val2: r2
    CASE val3: r3
}

也就是说 VAL 事物需要向下评估,因此对于您偶然发现的情况,您正在编写额外的布尔逻辑,它可以解析为布尔答案。作为 doc's note,要使 expression 匹配 value,它们需要属于同一类型才能自动转换。

因此会出现 SQL 错误:

select 
    case false
    when true then 1
    when 'bob' then 2
end;

Boolean value 'bob' is not recognized

因为第二个值无法自动转换为与 case 表达式相同的类型,这是一个布尔值。