LeetCode刷题第一周

本周开始每周一更新LeetCode刷题系列,坚持每周刷一些各方面的面试题,每周一做一篇大致总结,这个系列轻松一点,每篇开篇都放一张好看的图片,大家可以点个赞捧捧场哈,努力坚持一下,争取在面试时造出自己的小火箭,然后开始安心在厂里拧螺丝。

文章目录

  • 数据库专题
    • 简单
      • 175. 组合两个表
      • 176. 第二高的薪水
      • 181. 超过经理收入的员工
      • 182. 查找重复的电子邮箱
      • 183. 从不订购的客户
      • 196. 删除重复的电子邮箱
      • 197. 上升的温度
    • 中等
      • 177. 第N高的薪水
      • 178. 分数排名
      • 180. 连续出现的数字
      • 184. 部门工资最高的员工
    • 困难
      • 185. 部门工资前三高的所有员工
      • 262. 行程和用户


数据库专题

LeetCode刷题第一周_第1张图片

简单

175. 组合两个表

题目链接:点击传送至本题

题目大意:
Person表(PersonId、FirstName、LastName)Addres表(AddressId、PersonId、City、State),要求:无论Person是否有地址信息,都要基于两表查询 Person的以下信息:FirstName, LastName, City, State。

解题思路:
考虑到并不是每个人都有地址信息,所以应该使用外连接(本题中是left join)。

# 175. 组合两个表
select FirstName, LastName, City, State
from Person
left join Address
on Person.PersonId=Address.PersonId;

176. 第二高的薪水

题目链接:点击传送至本题

题目大意:
Employee表(Id,Salary),要求:查询出该表第二高的薪水(查询出的字段名改为SecondHighestSalary ),如果不存在第二高的薪水,查询返回null。

解题思路:

方法1:
先查询一次最高工资,然后在补集中再次查询最高工资即可;
可以这样做是因为sql的聚合函数max自带查询不到返回null的特性。

方法2:
将不同的薪资降序排序,然后使用limit函数截取第二高的工资。
但是可能不存在第二高的薪水,可能表只有一条记录,
所以要考虑当查询不到时返回null值,使用临时表子查询或ifnull函数都可以解决这个问题。

# 176. 第二高的薪水

#方法1:
select max(Salary) as SecondHighestSalary 
from Employee 
where Salary < (select max(Salary) from Employee);

#方法2:
select ifnull(
    (select distinct Salary
    from Employee
    order by Salary desc
    limit 1,1),null) as SecondHighestSalary 

181. 超过经理收入的员工

题目链接:点击跳转至本题

题目大意:
Employee表(Id,Name,Salary,ManagerId),经理也属于员工,要求:查询出薪水高于他们的经理的员工的姓名。

解题思路:
由于经理也是员工,所以可以通过内连接,自己连接自己,则表1为员工,表2为经理。查询超过经理收入的员工,需要再加上判断条件→表1.Salary>表2.Salary。

# 181. 超过经理收入的员工
select e1.Name as "Employee"
from Employee e1 
inner join Employee e2 
on e1.ManagerId=e2.Id
where e1.Salary>e2.Salary;

182. 查找重复的电子邮箱

题目链接:点击跳转至本题

题目大意:
Person表(Id、Email),要求查询出Person表中所有重复的电子邮箱。

解题思路:
方法1:
使用group by对Email字段分组后,添加having筛选条件。

方法2:
使用group by和count函数计算每个Email的存在次数作为临时表,然后对临时表添加筛选条件即可。

# 182. 查找重复的电子邮箱

# 方法1:
select Email
from Person
group by Email
having count(Email)>1;

# 方法2:
select Email
from(
    select Email,count(Email) num
    from Person 
    group by Email
) as table_1
where num>1;

183. 从不订购的客户

题目链接:点击跳转至本题

题目大意:
Customers表(Id、Name)Orders表(Id、CustomerId),要求:找出所有从不订购任何东西的客户。(即Customers表中Id不在Orders表的CcustomerId字段的Name)

解题思路:
查询从不订购的客户,可以先将订购过商品的客户id查询出来,然后使用not in查询不在此列表中的用户。

# 183. 从不订购的客户

select c.Name as 'Customers'
from Customers c
where c.id not in(select CustomerId from Orders);

196. 删除重复的电子邮箱

题目链接:点击跳转至本题

题目大意:
Person表(Id、Email),要求删除Person表Email字段中所有重复的数据,删除时保留Id最小的那个数据。

解题思路:
通过Email字段将Person表与自身自连接起来,形成笛卡尔积,然后删除Id更大的那些数据,剩下的就是重复且Id最小的数据。

# 196. 删除重复的电子邮箱

delete p1
from(
    Person as p1
    inner join Person p2
    on p1.Email=p2.Email
) where p1.Id>p2.Id;

197. 上升的温度

题目链接:点击跳转至本题

题目大意:
Weather表(Id、RecordDate(DATE)、Temperature),要求查找比昨天温度高的日期的Id。

解题思路:

# 197. 上升的温度

select w1.Id as Id
from Weather w1
inner join Weather w2
on datediff(w1.RecordDate,w2.RecordDate)=1
where w1.Temperature>w2.Temperature;

在这里插入图片描述

中等

177. 第N高的薪水

题目链接:点击跳转至本题

题目大意:
Employee表(Id、Salary),要求查出表中第 n 高的薪水。

解题思路:
针对Employee表的Salary字段降序排列,使用limit限定语句限定范围为第n条。需要注意的是limit的下标默认从0开始,需要设定局部变量解决这一问题。

# 177. 第N高的薪水
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
  set n=N-1;
  RETURN (
    select ifnull(
    (select distinct Salary
    from Employee
    order by Salary desc
    limit n,1),null)
  );
END

178. 分数排名

题目链接:点击跳转至本题

题目大意:
Scores表(Id、Score),要求依据Score分数进行排名,如果分数相同,则分数排名相同,且名次之间无间隔。

解题思路1:
给你一个分数X,如何计算出其排名Rank? 首先将所有大于等于X的分数提取为一个集合,然后去重剩下的个数就是X的排名Rank。

解题思路2:
使用mysql8.0之后引入的dense_rank() over()函数

# 178. 分数排名

#方式1:
select s2.Score as Score,
(select count(distinct s1.Score) from Scores s1 where s1.Score>=s2.Score) as "Rank"
from Scores s2
order by s2.Score desc;
# 方式2:
select Score, dense_rank() over (order by Score desc)  as "Rank"
from Scores;

180. 连续出现的数字

题目链接:点击跳转

题目大意:
Logs表(Id,Num),要求查出Num至少连续出现三次的数字。

解题思路:
直接使用sql92语法对Logs做两次自连接,三张表做笛卡尔积,筛选条件是三张表的Id连续的同时Num相等。另外记得加上distinct去重。

# 180. 连续出现的数字
select distinct l1.Num as "ConsecutiveNums"
from 
    Logs as l1,
    Logs as l2,
    Logs as l3
where
    l1.Id=l2.Id-1
    and l2.Id=l3.Id-1
    and l1.Num=l2.Num
    and l2.Num=l3.Num;

184. 部门工资最高的员工

题目链接:点击跳转

题目大意:
Employee表(Id,Name,Salary,DepartmentId)Department表(Id,Name),要求查找出每个部门工资最高的员工。

解题思路:
可以先在员工表中的各个部门内查询最高工资作为临时表,然后再把两张表做内连接,方便查询到部门名,此时需要使用IN语句来挂载之前查询到的临时表

# 184. 部门工资最高的员工
select d.Name Department,e.Name Employee,e.Salary Salary
from Employee e
inner join Department d
on e.DepartmentId=d.Id
where (e.DepartmentId,e.Salary) in(
    select DepartmentId,max(Salary)
    from Employee
    group by DepartmentId
);

困难

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

题目链接:点击跳转

题目大意:
Employee表(Id,Name,Salary,DepartmentId)Department表(Id,Name),要求查询出每个部门前三高工资的所有员工。有相同工资的保留。

解题思路:
前三高的薪水意味着有不超过3个工资比这些值大,据此可以写出下列sql语句。然后再连接上部门表,注意连接后的筛选条件即可。

select e1.Name as 'Employee', e1.Salary
from Employee e1
where 3 >
(
    select count(distinct e2.Salary)
    from Employee e2
    where e2.Salary > e1.Salary
);
# 185. 部门工资前三高的所有员工
select 
    d.Name "Department",e1.Name "Employee",e1.Salary "Salary"
FROM 
    Employee e1
    inner 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
)

262. 行程和用户

题目链接:点击跳转

题目大意:
Trips出租车表(Id,Client_Id,Driver_Id,City_Id,Status,Request_at)Users用户表( Users_Id,Banned,Role),要求查出 2013年10月1日 至 2013年10月3日 期间非禁止用户的取消率,保留两位小数。

取消率的计算方式如下:(正常用户取消的订单数量) / (正常用户的订单总数)

解题思路:
将client_id和driver_id各自关联上users_id,同时检测是否被禁止。在此基础上,按照日期分组、查询正常用户取消的订单数量(count(status))、正常用户的订单总数if(T.STATUS=‘completed’,0,1)。

# 262. 行程和用户
select T.Request_at as "Day",round(
    sum(if(T.STATUS='completed',0,1))/count(T.STATUS),2
) as "Cancellation Rate"
from Trips as T
join Users as U1 ON (T.client_id =U1.users_id and U1.banned = 'No')
join Users as U2 ON (T.driver_id =U2.users_id and U2.banned = 'No')
where T.request_at BETWEEN '2013-10-01' and '2013-10-03'
group by T.request_at

你可能感兴趣的:(#,LeetCode刷题)