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 = true
和 false = 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 表达式相同的类型,这是一个布尔值。
直到今天,我仍然认为 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 = true
和 false = 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 表达式相同的类型,这是一个布尔值。