MySQL 解决查询NULL的问题
题意分析
题目很简单:有一个 Employee 表,表里有两个字段:id(职工号)、salary(工资)。要求查询第二大的工资数,展示项名为:SecondHighestSalary
难点: 当第二大的工资不存在的时候,查询结果为 NULL
解题思路
首先我们先忽略工资不存在的情况,只解决“第二大”这个问题。所谓“第二大”,因为通常我们比较容易拿到“第一大”(即最大值),所以我们转换一下概念,即去掉“第一大”后,剩下的“第一大”即“第二大”。确定这一概念之后,便很好做了。常见的解决方法如下:
第一种方式,分解二个步骤,代码如下:
-- 按 salary 倒序,取前两个值
SELECT DISTINCT(salary) FROM employee
ORDER BY salary DESC
LIMIT 2;
-- 将上述结果 按 salary 升序,取第一个值
SELECT t.salary AS 'SecondHighestSalary'
FROM (
SELECT DISTINCT salary
FROM employee
ORDER BY salary DESC
LIMIT 2
) t
ORDER BY t.salary ASC
LIMIT 1;
第二种思路,和上面类似,只是倒序后,直接利用 MIN() 方法,取最小值:
SELECT MIN(t.salary) AS 'SecondHighestSalary'
FROM (
SELECT DISTINCT salary
FROM employee
ORDER BY salary DESC
LIMIT 2
) t
第三种思路,也是分三步骤,先找到最大值,然后从全集里排除最大值,最后从子集里找最大值:
-- 查找最大值
SELECT MAX(salary) FROM employee;
-- 从全集里排除最大值
SELECT salary FROM employee WHERE salary != (
SELECT MAX(salary) FROM employee
)
-- 从上面得到的子集里,找最大值
SELECT MAX(salary) FROM employee WHERE salary != (
SELECT MAX(salary) FROM employee
)
第四种思路,利用 limit offset,limit 表示取多少个值,offset 表示偏移量,所以代码如下:
SELECT DISTINCT(salary) AS SecondHighestSalary FROM employee
ORDER BY salary DESC
LIMIT 1 OFFSET 1;
接着,我们来解决当“第二大”不存在时,需要返回 NULL 的问题。我们可以先自己创建 table,然后插入数据,执行上面的语句,当然也可以在 leetcode 上进行 debug。
可以发现第一和第二种思路,当数据不存在时,是有 bug 的,因为取最小值和取第一个值,都会取到一个值,除非整个 table 数据都是空的。这两种思路暂时排除(后面也会给出这两种思路下的解决方法)。
第三种思路,执行一下,结果很happy,符合题目要求,即便是数据不存在时,也会返回 NULL,好了,你已经完成了这个题目。
第四种思路,执行一下,当数据不存在时,返回的结果集为 空,并没有返回 NULL。
这里我们需要了解两个知识点,首先,对于 max()、min()、sum() 聚合函数,当值不存在时,会返回 NULL,因此我们的第三种思路可以满足题目要求。其次,SELECT 结果集; 可满足要求。它等价于 SELECT NULL;
因此我们的第四种方式,可写为:
SELECT (
SELECT DISTINCT salary AS SecondHighestSalary
FROM employee
ORDER BY salary DESC
LIMIT 1, 1
) AS SecondHighestSalary;
扩展
如果我们不知道 MAX 和 SELECT 结果集 这两种方式,有没有办法做出来呢?当然也是有的。也就是我们去扩展上面说到的第一和第二种思路,通过结合 LEFT JOIN 或 RIGHT JOIN。为什么会想到 LEFT JOIN 呢,很明显,不存在的结果却需要显示为 NULL,这很符合 LEFT JOIN 或 RIGHT JOIN 的特质。直接上代码:
SELECT if(m.salary2 IS NULL, NULL, m.salary1) AS SecondHighestSalary
FROM (
SELECT t1.salary AS 'salary1', t2.salary AS 'salary2'
FROM employee t1
LEFT JOIN (
SELECT salary
FROM employee
ORDER BY salary DESC
LIMIT 1
) t2
ON t1.salary < t2.salary
ORDER BY t1.salary DESC
LIMIT 2
) m
ORDER BY m.salary1 ASC
LIMIT 1
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- 【Pytorch 】笔记二:动态图、自动求导及逻辑回归
- 听说国漫最近崛起了,那我们就来爬几部国漫看看(动态加载,反爬)
- 微信小程序开发实战(25):预览图像
- 【Pytorch】笔记三:数据读取机制与图像预处理模块
- 表白利器,马赛克拼贴照片制作
- 【014期】JavaSE面试题(十四):基本IO流
- 微信小程序开发实战(24):选择图像
- 反 996 有理:催程序员交代码,写不出好软件
- 一千个不用 Null 的理由!
- WebAssembly 是 Deno 的好搭档
- Chrome开发者工具的11个高级使用技巧
- 怒爬某破Hub站资源,简单4步撸个鉴黄平台!
- 审阅“史上”最烂的代码
- BeanUtils 是用 Spring 的还是 Apache 的好?
- 一看就会的mysql索引优化(真实案例)