为何调整DENSE_RANK()与IFNULL()查询顺序后返回空而非NULL?
问题分析:为何调整SQL查询顺序后返回空而非NULL?
测试表结构
| id | number |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
需求说明
需要返回表中第二大的number值,若不存在第二大值则返回NULL。当前表中所有number均为1,无第二大值,预期返回NULL。
可正常生效的SQL语句
SELECT IFNULL(( SELECT number FROM (SELECT *, DENSE_RANK() OVER(ORDER BY number DESC) AS ranking FROM test) r WHERE ranking = 2), NULL) AS SecondHighestNumber;
调整顺序后失效的SQL语句
SELECT IFNULL(number, NULL) AS SecondHighestNumber FROM (SELECT *, DENSE_RANK() OVER(ORDER BY number DESC) AS ranking FROM test) r WHERE ranking = 2;
原因分析
核心差异在于IFNULL的作用范围和查询返回结果的本质:
- 第一个语句中,内层的标量子查询
SELECT number FROM ... WHERE ranking=2在没有匹配行时,会直接返回NULL(这是标量子查询的特性:无结果时返回单个NULL值)。外层的IFNULL只是做了一层兜底(其实这里IFNULL可以省略,因为子查询本身就会返回NULL),最终会输出一行值为NULL的结果。 - 第二个语句中,
WHERE ranking=2没有匹配到任何行,整个查询直接返回空结果集(没有任何数据行)。而IFNULL(number, NULL)是对查询结果中每一行的number字段做判断,但根本没有行被返回,IFNULL的逻辑完全没机会触发,自然就输出空结果,而非包含NULL的一行。
简单总结:第一个语句是先让子查询返回NULL,再包装输出一行;第二个语句是先过滤行,没行就直接返回空,IFNULL根本没执行的机会。
内容的提问来源于stack exchange,提问作者Lkiia
相关产品推荐
相关产品推荐

