【LeetCode高频SQL50题-基础版】打卡第8天:第41~45题

文章目录

【LeetCode高频SQL50题-基础版】打卡第8天:第41~45题

⛅前言

在这个博客专栏中,我将为大家提供关于 LeetCode 高频 SQL 题目的基础版解析。LeetCode 是一个非常受欢迎的编程练习平台,其中的 SQL 题目涵盖了各种常见的数据库操作和查询任务。对于计算机科班出身的同学来说,SQL 是一个基础而又重要的技能。不仅在面试过程中经常会遇到 SQL 相关的考题,而且在日常的开发工作中,掌握 SQL 的能力也是必备的。

本专栏的目的是帮助读者掌握 LeetCode 上的高频 SQL 题目,并提供对每个题目的解析和解决方案。我们将重点关注那些经常出现在面试中的题目,并提供一个基础版的解法,让读者更好地理解问题的本质和解题思路。无论你是准备找工作还是提升自己的技能,在这个专栏中,你可以学习到很多关于 SQL 的实践经验和技巧,从而更加深入地理解数据库的操作和优化。

我希望通过这个专栏的分享,能够帮助读者在 SQL 的领域里取得更好的成绩和进步。如果你对这个话题感兴趣,那么就跟随我一起,开始我们的 LeetCode 高频 SQL 之旅吧!

好友申请II

🔒题目

题目来源:602.好友申请II:谁有最多的好友

🔑题解

  • 考察知识点子查询union all

分析:我的思路是先分别统计 requester_id 和 accepter_id 这两列 id 出现的次数,然后将这两个统计结果使用 union all 聚合起来,基于这张聚合的临时表作最终的统计

1)分别统计 requester_id 和 accepter_id,使用 union all 对结果进行一个合并

注意:这里一定要使用 union all,而不是 union,因为 union 会直接将查询的结果进行去重,按照题目的含义,这里是不需要进行去重的,两列 id 出现的次数都需要进行统计的

mysql 复制代码
select requester_id id, count(*) num
from RequestAccepted
group by requester_id
union all
select accepter_id id, count(*) num
from RequestAccepted
group by accepter_id
mysql 复制代码
| id | num |
| -- | --- |
| 1  | 2   |
| 2  | 1   |
| 3  | 1   |
| 2  | 1   |
| 3  | 2   |
| 4  | 1   |

2)基于上面的表进行一个最终的结果获取

这一部就相当简单, 可以直接对按照 id 进行一个分组,然后使用 sum 聚合函数统计每一个 id 出现的次数,最终在降序排序,limit截取第一个元素,即可筛选出最终的结果

mysql 复制代码
select id, sum(num) num
from(
    select requester_id id, count(*) num
    from RequestAccepted
    group by requester_id
    union all
    select accepter_id id, count(*) num
    from RequestAccepted
    group by accepter_id
) t
group by id
order by num desc
limit 1;

2016年的投资

🔒题目

题目来源:585.2016年的投资

🔑题解

  • 考察知识点roundsum子查询group byinhavingcount

分析:这一题题意还算十分清晰,我们只需要按照题目要求一步一步来即可,题目要求我们查询出满足下面两个条件的所有投保人的在2016年的总金额

  1. 在 2015 年的投保额 (tiv_2015) 至少跟一个其他投保人在 2015 年的投保额相同。
  2. 所在的城市必须与其他投保人都不同(也就是说 (lat, lon) 不能跟其他任何一个投保人完全相同)

我的思路是,先查询出满足第一个条件的所有 tiv_2015,然后插叙出所有满足第二个条件的 lat 和 lon,再将这两个条件进行取一个交集,最周在利用 sum + round 函数对筛选出的记录进行一个求和,最后就可以得到最终的答案了

1)查询出满足第一个条件的所有的 tiv_2015

mysql 复制代码
select tiv_2015
from Insurance 
group by tiv_2015
having count(*) > 1
复制代码
| tiv_2015 |
| -------- |
| 10       |

2)查询出满足第二个条件的所有的 lat 和 lon

这里可以巧妙的利用 group by进行两个字段的分组,可能平常我们都是使用一个字段进行分组,实际上 group by可以同时按照多个字段进行分组

mysql 复制代码
select lat, lon
from Insurance
group by lat, lon
having count(*) = 1
复制代码
| lat | lon |
| --- | --- |
| 10  | 10  |
| 40  | 40  |

3)利用 in 和 and 使用上面两个结果集进行交集,然后筛选出符合所有条件的记录,最终通过 round 和 sum 进行最终的计算

mysql 复制代码
select round(sum(tiv_2016), 2) tiv_2016
from Insurance
where tiv_2015 in (
    select tiv_2015
    from Insurance 
    group by tiv_2015
    having count(*) > 1
) and (lat, lon) in (
    select lat, lon
    from Insurance
    group by lat, lon
    having count(*) = 1
);

部门工资前三高的所有员工

🔒题目

题目来源:185.部门工资前三高的所有员工

🔑题解

  • 考察知识点dense_rank子查询自连接countdistinct

分析:这一题最开始我的第一反应就是使用窗口函数,因为这种分组排序使用窗口函数将十分的方便,具体的思路如下

  1. 确定使用哪一个窗口函数,这里可以明确使用 dense_rank 窗口函数(并列排序,不会跳过重复的序号 1、1、2)
  2. 剩下的就很好办的,我们只需要筛选出排名前三的即可

1)利用窗口函数对所有的记进行员工分组排序

mysql 复制代码
select *, dense_rank() over(partition by d.name order by salary desc) ranking
from Department d left join Employee e on d.id = e.departmentId
复制代码
| id | name  | id | name  | salary | departmentId | ranking |
| -- | ----- | -- | ----- | ------ | ------------ | ------- |
| 1  | IT    | 4  | Max   | 90000  | 1            | 1       |
| 1  | IT    | 6  | Randy | 85000  | 1            | 2       |
| 1  | IT    | 1  | Joe   | 85000  | 1            | 2       |
| 1  | IT    | 7  | Will  | 70000  | 1            | 3       |
| 1  | IT    | 5  | Janet | 69000  | 1            | 4       |
| 2  | Sales | 2  | Henry | 80000  | 2            | 1       |
| 2  | Sales | 3  | Sam   | 60000  | 2            | 2       |

2)筛选出排名前三的员工信息

mysql 复制代码
select  Department, Employee, salary
from(
    select d.name Department, 
       e.name Employee,
       e.salary,
       dense_rank() over(partition by d.name order by salary desc) ranking
    from Department d left join Employee e on d.id = e.departmentId
) t
where ranking <= 3 and salary is not null

窗口函数虽然好用,但是MySQL的版本必须是8或8以上才能使用,所以我们还是有必要掌握使用不同函数进行操作

分析:我们进行一个自连接,然后统计出所有排名在前三的员工信息

mysql 复制代码
select d.name Department, e1.name Employee, e1.salary
from Employee e1 join Department d on e1.DepartmentId = d.id 
where 3 > (
    select count(distinct e2.salary)
    from Employee e2
    where e2.salary > e1.salary and e1.DepartmentId = e2.DepartmentId
);

下面这个SQL是含义是查询出比当前员工(e1)薪资高的员工数量,因为比排名第一员工薪资高的员工数量为0,所以计数是从0开始,并不像先前窗口函数中排名是从1开始的,所以这里 3 是大于,不能取等号

mysql 复制代码
    select count(distinct e2.salary)
    from Employee e2
    where e2.salary > e1.salary and e1.DepartmentId = e2.DepartmentId

PS:说实话这个SQL是我看官方题解是摘自官方题解,一开始看着是有点懵的,后面多看几遍才理解了,我个人任务使用窗口函数更易于理解,同时窗口函数提的SQL比这条SQL效率更高(窗口函数的SQL是90%左右,这条SQL是50%左右)

修复表中的名字

🔒题目

题目来源:1667.修复表中的名字

🔑题解

  • 考察知识点substringupperlowerconcat

    • substring(column_name, start, length):这将从列的值中提取一个子字符串,从指定的起始位置开始,直到指定的长度。注意截取索引是从1开始的,不是0
    • upper(expression):这会将字符串表达式转换为大写。
    • lower(expression):这会将字符串表达式转换为小写。
    • concat(string1, string2, ...):这会将两个或多个字符串连接成一个字符串。

    PS:这里只是讲解这些函数大概的作用,关于这些函数的详细使用大家可以参考MySQL教程

分析:这一题其实说简单也简单,说难也难,因为只要你有了解相关操作字符的 函数 可以秒杀这一题,如果你并不了解相关的 函数 可能就毫无头绪,所以大家在做题的时候,不要去死磕题目,没做出来可以适当的直接看题解

mysql 复制代码
select user_id, concat(upper(substring(name, 1, 1)), lower(substring(name, 2, length(name)-1))) name
from Users
order by user_id asc;

备注:substring(name, 2, length(name)-1)这个函数可以简写为substring(name, 2)

患某种疾病的患者

🔒题目

题目来源:1572.患某种疾病的患者

🔑题解

  • 考察知识点like

分析:直接使用 like 就可以了,但是需要注意一些比较细节的地方,DIAB1不一定出现在第一个位置,可以是第二个单词的位置,但是不能使用%DIAB1%去过滤,需要使用% DIAB1%这个去过滤,因为它是单词首位

mysql 复制代码
select *
from Patients
where conditions like 'DIAB1%' or conditions like '% DIAB1%';

这里再推荐一种更加简洁的写法,直接使用正则表达式,没想到正则表达式无处不在,在MySQL中也可以使用正则表达式,不得不说正则表达太强大了

mysql 复制代码
select patient_id, patient_name, conditions
from Patients
where conditions REGEXP '\\bDIAB1.*';
相关推荐
陈卓41027 分钟前
MySQL-主从复制&分库分表
android·mysql·adb
你都会上树?1 小时前
MySQL MVCC 详解
数据库·mysql
长征coder2 小时前
AWS MySQL 读写分离配置指南
mysql·云计算·aws
ladymorgana3 小时前
【docker】修改 MySQL 密码后 Navicat 仍能用原密码连接
mysql·adb·docker
PanZonghui3 小时前
Centos项目部署之安装数据库MySQL8
linux·后端·mysql
GreatSQL社区3 小时前
用systemd管理GreatSQL服务详解
数据库·mysql·greatsql
掘根3 小时前
【MySQL进阶】错误日志,二进制日志,mysql系统库
数据库·mysql
weixin_438335403 小时前
基础知识:mysql-connector-j依赖
数据库·mysql
小明铭同学3 小时前
MySQL 八股文【持续更新ing】
数据库·mysql
许愿与你永世安宁4 小时前
力扣343 整数拆分
数据结构·算法·leetcode