为什么 null 值在 mysql 中排名不同?

Why null values are not ranking same in mysql?

昨天问了一个关于学生分数排名的问题

[ ]

我实际上是在其他问题的帮助下解决了我的问题(感谢所有帮助过我的人)。
与此同时,我无意中想通了一些事情。如果我尝试按学生的分数对我的学生进行排名,并且如果分数列为空(NULL),我的查询也没有给出错误,它也将排名排序为 1-2-3-4,但所有值都是 NULL

这是我试过的查询

select er.*,
       (@rank := if(@points = points, 
                    @rank, 
                    if(@points := points,    
                       @rank + 1, 
                       @rank + 1                       
                      )
                   )                  
       ) as ranking
from examresults er cross join
     (select @rank := 0, @points := -1) params
order by points desc;

这就是结果。

所以我想知道 NULL 值是否相同?这个查询不应该为我数据库中的每个用户提供 排名 1 吗?为什么它会递增地对空值进行排名?

你比较 @points = points 结果是 @points=NULL

但是与 NULL 的任何比较都会导致 UNKNOWN:

value= NULL -> UNKNOWN
value<>NULL -> UNKNOWN
value< NULL -> UNKNOWN
value> NULL -> UNKNOWN

即使 NULL=NULL 也会导致 UNKNOWN

当然也有例外:

DISTINCTGROUP BY 认为 NULL 相等。

NULL 没有值 - 它是 non-existence 的状态。所以任何基于 NULL 的结果都是 non-deterministic。您应该明确处理 NULL 值的可能性。

很多人认为 NULL 的意思是 no valuenon-existent。甚至 Wikipedia 也是这样解释的。

把它想象成 unknown value 一切都会更有意义。

一个人无法比较两个 unknown values 因为,嗯,他们是未知的。它们不相等,但也不相同。 None 个大于另一个。

两个unknown values比较的结果也是一个unknown value(即NULL)。

布尔比较return真、假,或者NULL,一般把NULL当作假。您可以轻松修改查询以使用 NULL-safe equality:

select er.*,
       (@rank := if(@points <=> points, 
                    @rank, 
                    if(@points := points,    
                       @rank + 1, 
                       @rank + 1                       
                      )
                   )                  
       ) as ranking
from examresults er cross join
     (select @rank := 0, @points := -1) params
order by points desc;