Oracle中Null和无值的区别

本文通过Leetcode题目解析SQL中如何查询第二高的薪水,并探讨了不同情况下结果集显示null或空的区别,以及使用NVL函数的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以Leetcode第176题“第二高的薪水”为例。
在这里插入图片描述
在这里插入图片描述
首先说一下这道题最容易理解、最容易实现的解法,就是比最大值小的值里最大的值。

SELECT MAX(salary) AS SecondHighestSalary
FROM Employee
WHERE salary < (SELECT MAX(salary) 
                FROM Employee)

通过这道题目,我来说明一下,什么时候结果集显示的是null,什么时候是空。下面这个是我们的测试用例,也就是只有一个值,第二高的薪水也就是null。
在这里插入图片描述
用上面的语句搜索,结果是下面这样的。
在这里插入图片描述
如果你把SQL改成下面这样,也就是去掉MAX函数,结果就变成了空。可以看到输出为null与MAX有关系。

SELECT salary AS SecondHighestSalary
FROM Employee
WHERE salary < (SELECT MAX(salary) 
                FROM Employee)

在这里插入图片描述
我们在利用这个题目试验一些别的东西,比如说取rownum为2的行,对于这个测试用例应该为null,可以发现输出的结果为空。(这道题不能这么做,因为还有重复值的问题,只是举个例子)

SELECT a.salary AS SecondHighestSalary
FROM (SELECT rownum r, e.*
      FROM Employee e) a
WHERE a.r = 2

在这里插入图片描述
如果我们像上面一样加个MAX函数,输出结果就会为null。

SELECT MAX(a.salary) AS SecondHighestSalary
FROM (SELECT rownum r, e.*
      FROM Employee e) a
WHERE a.r = 2

在这里插入图片描述


如果我们在套一个SELECT,也可以输出为null。

SELECT(
    SELECT a.salary
    FROM (SELECT rownum r, e.*
          FROM Employee e) a
    WHERE a.r = 2
) AS SecondHighestSalary
FROM dual

在这里插入图片描述
对于MySQL来说也是这样的,只不过由于语法原因,它不要FROM dual。这个评论区也有人询问,这个解释我觉得没解释出什么,但不知道为什么这么多赞。
在这里插入图片描述
在这里插入图片描述


那NVL不行吗?
可以看到这种方式也是输出为空。

SELECT NVL(a.salary, null) AS SecondHighestSalary
FROM (SELECT rownum r, e.*
      FROM Employee e) a
WHERE a.r = 2

在这里插入图片描述
但是如果你像下面这么写,输出的则是null(确实是由于NVL而输出的,把NVL第二个参数改成别的输出的内容也会变),很奇怪。这也是这道题目Oracle解法大部分人都采用的办法。包括MySQL也是如此。我也不知道为什么,网络上也查不到,只能强行理解SELECT这个语句,放到一个函数里,自己可能也相当于是一个函数(因为NVL只会获取null,所以说明里面SELECT出来就已经是null了,也可以发现,NVL对于这道题没啥用,直接SELECT一个SELECT就可以了)。

SELECT NVL((SELECT a.salary
            FROM (SELECT rownum r, e.*
                  FROM Employee e) a
            WHERE a.r = 2), null) AS SecondHighestSalary
FROM dual

在这里插入图片描述
MySQL的例子:
在这里插入图片描述

我找了两道我用过NVL的题目,发现一个是左连接,一个全连接,它们这种在JOIN时没有值会直接补null,所以用NVL就可以。

SELECT name, NVL(SUM(distance), 0) AS travelled_distance
FROM Users u LEFT JOIN Rides r
  ON u.id = r.user_id
GROUP BY u.id, u.name
ORDER BY travelled_distance DESC, u.name
----------------------------------------------------------
SELECT NVL(e.employee_id, s.employee_id) AS employee_id
FROM Employees e FULL OUTER JOIN Salaries s
  ON e.employee_id = s.employee_id
WHERE e.name IS NULL OR s.salary IS NULL
ORDER BY 1

总结

如果一个查询是没有结果的,你如果想让输出是null,有两种方式

  1. 用一个函数,像MAX、MIN等,去包住这个SELECT的值。该怎么理解呢?我也不知道,我觉可以理解为一个函数的参数为空,输出结果就是null。
  2. 你可以在这个SELECT的外面在套一个SELECT,该怎么理解呢?我觉得就是SELECT空,输出就是null。
  3. 额外说一下NVL,NVL是遇见null才会起作用的,遇见空是不起作用的。如果想让它起作用可以在NVL里包一个SELECT语句,强行理解,可以说把这个语句变成“函数”,这样就会输出null。
补充

这个文章是说MySQL里ifnull的,也证明了我的猜想:地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fisherman_sail

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值