无法理解SQL中的CASE WHEN语句

时间:2016-11-05 05:44:38

标签: mysql

SELECT    state, 
    COUNT(CASE WHEN elevation >= 2000 THEN 1 ELSE NULL END) as count_high_elevation_aiports 
FROM airports 
GROUP BY state;
  

在上面的陈述中,什么是THEN 1以及' 1'表示?   这个价值如何' 1'那么这会影响输出吗?

2 个答案:

答案 0 :(得分:2)

首先,请注意这三个表达式是等效的:

CASE WHEN elevation >= 2000 THEN 1 ELSE NULL END
IF(elevation >= 2000, 1, NULL)
((elevation >= 2000) OR NULL)

如果提升> = 2000,则表达式的计算结果为“1”,否则表达式的计算结果为NULL

“1”通常用作布尔值true,你可以用上述表达式中的MySQL文字TRUE替换相同的结果......但这不是“1”的用途。

COUNT()一起使用时,在这种情况下,1的唯一真正意义在于它不是NULL

这很重要,因为 - 与普遍看法相反 - COUNT()不计算行数。它会计算价值。

有什么区别? NULL在技术上不是一个价值。相反,它是表示值的缺席的标记,因此COUNT(expr)仅计算 expr 不为空的行。

通过使用类似于此处的表达式,您要求服务器使用elevation =>计算行数。 2000,你可以通过给COUNT()一个NULL表示你想要不计算的行...以及你做的行的非空值来实现这一点。

Aggregate (GROUP BY) functions进行操作 - 而NULL再次不是这个意义上的值。

使这个基本原理可能更加清晰的另一个聚合函数是AVG()。如果您有3行...值为5,NULL和10 ...平均值是多少?如果你说7.5,那是正确的:这3行的平均值是(5 + 10)÷2 = 5,因为3行只有两个值。 NULL不为0,否则平均值为(5 + 0 + 10)÷3 = 5,而不是。

所以,这就是它的工作原理和原因。

  

THEN后的值'1'如何影响输出?

它确实没有。您可以轻松地说COUNT(CASE WHEN elevation >= 2000 THEN 'cat videos are funny' ELSE NULL END)因为,就像文字1一样,文字字符串'cat videos are funny'也不是空的,非空值 - 任何非空的 - 都是什么算在内。

新手可能会尝试使用COUNT(elevation >= 2000)来完成此任务,但这会给出错误的答案,因为对于高程为< 1的行,0(false) 2000不是null,所以这些行仍然会计算在内。

然后你可以问,“为什么不用COUNT(*) ... WHERE elevation >= 2000?”好问题。原因各不相同,但如果您GROUP BY state并且有些行没有匹配WHERE的行,那么这些状态将完全从结果中消除,这通常不是您想要的。此查询包含它们,计数为零。

请注意,((elevation >= 2000) OR NULL)(顶部的第三个示例表达式)实际上不需要括号。我把它们包括在内,因为这种形式乍一看并不是必需的。如果简单地编写elevation >= 2000 OR NULL,操作的自然优先级将导致正确评估它。此表达式与其他两个表达式相同,因为elevation >= 2000首先计算结果为1(如果为true),0表示为false,或NULL如果高程为空。然后评估优先级较低的OR,您会得到其中一个:1 OR NULL => 1 ... 0 OR NULL => NULL ... NULL OR NULL => NULL ...而您实际上可能会被授予当您使用COUNT(elevation >= 2000 OR NULL)编写查询时,互联网长老会使用SQL向导徽章。

答案 1 :(得分:1)

如果elevation>= 2000,则查询只会返回 1,否则会返回 NULL (这是用于布尔字段表示的完整,因为 NULL 表示 0 ), 现在返回的值将设置为 count_high_elevation_airports