高频 sql 50题(基础6)

六、子查询

1.上级经理已经离职的公司员工

题目描述

代码编写

select employee_id from Employees 
where salary<30000 and manager_id not in (select employee_id from Employees)
order by employee_id

2.换座位

题目描述

代码编写

select a.id,ifnull(b.student,a.student) as student
from Seat a left join Seat b 
on (case when mod(a.id,2)=1 then a.id=b.id-1 else a.id=b.id+1 end)

思路:

利用自连接,将表看成表a、表b,当id不能被2整除时,a.id=b.id-1(对应a.id=1,b.id=2);当id能被2整除时,a.id=b.id+1(对应a.id=2,b.id=1),完成学生1和学生2的座位互换,以此类推,筛选出a.id和b.student(a.id顺序输出,b.student是互换后的结果)。同时,当id为奇数时,最后一个学生没有可以互换座位,b.student输出结果为null,需要再加一个ifnull()判断,当输出结果为null,输出a.studnet即可。

3.电影评分

题目描述

代码编写

(select b.name as results 
from MovieRating as a left join Users b
on a.user_id=b.user_id
group by a.user_id
order by count(a.user_id) desc,b.name 
limit 1 )
union all
(select d.title  as results 
from MovieRating as c left join Movies d
on c.movie_id=d.movie_id
where c.created_at like "2020-02-%" 
group by c.movie_id
order by avg(c.rating) desc,d.title
limit 1)

Tip:

这道题使用的函数是 union all 而不是 union ,因为union all 遇到重复值也会保存下来,而union不会保留重复值,因此部分测试用例无法通过,如以下所示:

4.餐馆营业额变化增长

题目描述

代码编写

做法一(自连接):

select a.visited_on,
sum(b.amount) as amount,
round(sum(b.amount)/7,2) as average_amount
from(select distinct visited_on from Customer) a join Customer b 
on datediff(a.visited_on,b.visited_on) between 0 and 6
where a.visited_on>=(select min(visited_on) from Customer)+6
group by a.visited_on
order by a.visited_on

 思路:筛选出不重复的日期作为表a,与原表b连接,连接条件为表b日期在表a日期的6天前内,显示每个7天的信息(即日期与最小日期的差值大于或等于6),并计算消费总额和平均值。

做法二(利用窗口函数):

select 
visited_on,
total as amount,
round((total/7),2) as average_amount 
from(
    select 
    distinct visited_on,
    sum(amount) over(order by visited_on range interval 6 day preceding)as total 
    from Customer
    order by visited_on)as a
where datediff(visited_on,(select min(visited_on) from Customer))>=6

思路:窗口函数的思路和自连接的思路一致 ,它是直接计算每个当前日期以及前六天的消费总额(即使前面的数据不够,窗口函数也会将范围内的数据框住并计算),再筛选出每个第7天的信息。

5.好友申请

题目描述

代码编写

select ids as id,count(ids) as num from(
    select requester_id as ids from RequestAccepted
    where accept_date is not null
    union all
    select accepter_id as ids from RequestAccepted
    where accept_date is not null)as a
group by  ids
order by num desc
limit 1

思路:用 union all 函数将所有的请求的发起者和接受者联合在一列上,并按照 id 分组并统计每个id 出现的次数(要判断好友申请是否通过,即是否有接受好友申请日期),将统计结果倒序排序并取出第一条信息(即好友数量最多)。

6.2016年的投资

题目描述

代码编写

select round(sum(distinct a.tiv_2016),2) as tiv_2016 
from Insurance a join Insurance b
on a.pid!=b.pid and a.tiv_2015=b.tiv_2015
where (a.lat,a.lon) not in (
    select lat,lon from Insurance c
    where a.pid!=c.pid)

注意:要用 distinct 函数确保取得的 a.tiv_2016 不会重复,如果没有用 distinct 函数,a.tiv_2016分别会取到重复数据,在 a.ip=1 的时候筛选到 tiv_2016为5 和40,而在 a.ip=4 的时候筛选到  tiv_2016 为40 和5。

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

题目描述

 

代码编写

select Department, Employee, Salary from (
    select d.name as Department ,
     e.name as Employee , 
     e.salary as Salary , 
     dense_rank() over(partition by d.name order by e.salary desc) as rk 
     from Employee e left join Department d on e.departmentId = d.id) as a
     where a.rk <= 3;

思路:利用窗口函数对每个部门的工资高低进行排序,筛选出每个部门工资排名前三的信息。

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值