LeetCode力扣数据库题库-中等难度模式部分题解

177.第N高薪水

在这里插入图片描述

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
SET N=N-1;#用户变量
	 RETURN (
      # Write your MySQL query statement below.
      select ifnull(
	      (select distinct Salary 
	      from Employee
	      order by Salary desc
	      limit N,1)#limit N-1,1错误,limit后面不能带运算符,只能是常量
      ,null) getNthHighestSalary(N) 
     
      );
END

178.分数排名

在这里插入图片描述
在这里插入图片描述

select a.Score,count(distinct (b.Score)) as 'Rank'
from Scores a
join Scores b
on a.Score<=b.Score
group by a.Id
order by a.Score desc;

180.连续出现的数字

在这里插入图片描述
方式一

select distinct a.Num ConsecutiveNums
from Logs a
join Logs b
on a.Id=b.Id-1
join Logs c
on b.Id=c.Id-1
where a.Num=b.Num and b.Num=c.Num;

方式二

/*
select Num, 
    case 
      when @prev = Num then @count := @count + 1 #比较
      when (@prev := Num) is not null then @count := 1 #赋值1
    end as CNT
  from Logs, (select @prev := null,@count := null) as t #初始化变量
   #先将Num赋值给@prev,然后判断@prev是否为null,若是,则再把1赋值给@prev
   #@prev是用户变量 =是比较相等,:=是赋值
   */
   select distinct Num as ConsecutiveNums
from (
  select Num, 
    case 
      when @prev = Num then @count := @count + 1
      when (@prev := Num) is not null then @count := 1
    end as CNT
  from Logs, (select @prev := null,@count := null) as t
) as temp
where temp.CNT >= 3

184.部门工资最高的员工

在这里插入图片描述
在这里插入图片描述
步骤1:查找各个部门最大工资值
步骤2:在1的基础上找到对应部门名和员工名

select  d.Name Department,e.Name Employee,m.Salary
from (select max(Salary) Salary,DepartmentId
	from Employee 
	group by DepartmentId) m
join  Department d
on m.DepartmentId=d.Id
join Employee e 
on e.Salary=m.Salary and m.DepartmentId=e.DepartmentId

550.游戏玩法分析 IV

在这里插入图片描述
在这里插入图片描述
步骤1:查找首次登陆日期
步骤2:找第二次登陆和首次登陆时间差一天的玩家

select round(count(distinct a.player_id)/(select count(distinct player_id) from Activity),2) fraction
from Activity a
join (select min(event_date) event_date,player_id
from Activity
group by player_id) b
on a.player_id=b.player_id and datediff(a.event_date,b.event_date)=1

612.平面上最近的距离

在这里插入图片描述

select round(sqrt(pow((a.x-b.x),2)+pow((a.y-b.y),2)),2) shortest
from point_2d a,point_2d b
where concat(a.x,a.y)<>concat(b.x,b.y)#(a.x,a.y) != (a.x,a.y);a.x!=b.x or a.y!=b.y
order by sqrt(pow((a.x-b.x),2)+pow((a.y-b.y),2))
limit 1;

626.换座位

在这里插入图片描述
在这里插入图片描述

#case语句的简单方法
select (
	case 
	when id=(select count(*) from seat)and id%2=1 then id #MOD(id,2)
	when id%2=1 then id+1
	else id-1
	end
) id,student
from seat
order by id;

1193.每月交易1

在这里插入图片描述
在这里插入图片描述
date_format用法
注意分组后求approved 的总和方法

select date_format(trans_date,"%Y-%m") month,country,count(*) trans_count,sum(state='approved') approved_count,sum(amount) trans_total_amount,sum(amount*(state='approved')) approved_total_amount
from Transactions
group by country,date_format(trans_date,"%Y-%m")

1204.最后一个能进电梯的人

在这里插入图片描述
在这里插入图片描述
自连接的巧妙运用

select a.person_name
from Queue a
join Queue b
on a.turn>=b.turn
group by a.turn
having sum(b.weight)<=1000
order by sum(b.weight) desc
limit 1;

1205.每月交易

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从month来看。既包括transaction表中的日期,也包括chargebacks表中的日期,应该进行全连接,sql不支持full join 用union all来进行
思路:把chargebacks格式转换为transaction表,同时state可以写chargeback

select date_format(trans_date,'%Y-%m') month,country,ifnull(sum(state='approved'),0) approved_count,ifnull(sum(amount*(state='approved')),0) approved_amount,ifnull(sum(state='chargeback'),0) chargeback_count,ifnull(sum(amount*(state='chargeback')),0) chargeback_amount
from
(select * from Transactions 
union
(select trans_id id,country,'chargeback' state,amount,c.trans_date
from Chargebacks c join Transactions t
on c.trans_id=t.id)) a
group by date_format(trans_date,'%Y-%m'),country
having approved_amount>0 or chargeback_amount>0#忽略所有为0的行

1212.查询球队积分

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
思路:将teams表的id和matches表的host_id,guest_id连接,分析每个id作为主客场的情况。

select t.team_id,t.team_name,sum(case when t.team_id=m.host_team and host_goals>guest_goals then 3
when t.team_id=m.guest_team and host_goals<guest_goals then 3
when host_goals=guest_goals then 1 else 0 end) num_points#group by 之后可以直接求和
from Teams t
left join Matches m
on t.team_id=m.host_team or t.team_id=m.guest_team
group by team_id
order by num_points desc,team_id

1270.向公司CEO汇报工作的所有人

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
方式一:因为题中说明了经理之间的间接关系不会超过3个人,可以通过自连接来实现。

select c.employee_id 
join Employees b
on a.employee_id=b.manager_id and a.manager_id=1 #(a.employee_id 2,77-1;b.employee_id:4-2-1)
join Employees c
on b.employee_id=c.manager_id
where c.employee_id !=1

方式二

select employee_id from Employees 
where manager_id in
(
select employee_id from Employees
where manager_id in
(select employee_id from Employees where manager_id=1) 
) and employee_id<>1;

1285.找到连续区间的开始和结束数字

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
思路:可以分为三部分
1.找出所有连续区间的开始值,即让logs 表a,b自连接,同时a.log_id=b.log_id+1,b.log_id为null时,a.log_id为开始值。
1.找出所有连续区间的结束值,即让logs 表a,c自连接,同时a.log_id=c.log_id_1,c.log_id为null时,a.log_id为结束值。
3.开始值和结束值两张表的连接方式为:两表从小到大排列;开始值对应的结束值都要比其大;同时在比开始值打的范围内选取最小的就是其结束值。

select start_id,min(end_id) end_id
from(select a.log_id start_id
from Logs a
left join Logs b
on a.log_id=b.log_id+1 where b.log_id is null order by a.log_id) s
join (select a.log_id end_id
from Logs a
left join Logs c
on a.log_id=c.log_id-1 where c.log_id is null order by a.log_id) e
on s.start_id<=e.end_id
group by start_id
order by start_id

1321.餐馆营业额变化增长

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
思路:通过自连接算出来日期差在6以内所有订单的消费总和。
注意:2019-01-10 一天有两个订单,正确的计算应该是(130 + 110 + 140 + 150 + 80 + 110 + 130 + 150)/7 = 142.86。如果直接做自连接则(130 + 110 + 140 + 150 + 80 + 110 + 130 + 150)会被算两次。解决方法:先进行按天分组之后再自连接。

select a.visited_on,sum(b.amount) amount, round(avg(b.amount),2) average_amount
from (select sum(amount) amount,visited_on
from Customer
group by visited_on) a
left join (select sum(amount) amount,visited_on
from Customer
group by visited_on) b
on datediff(a.visited_on,b.visited_on) between 0 and 6
group by a.visited_on
having count(*)>=7
order by a.visited_on

1398. 购买了产品A和产品B却没有购买产品C的顾客

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意:=的范围和!= 的范围
如果是product_name !=C,输出的有1,2,3,达不到筛选的目的

select customer_id,customer_name
from Customers
where customer_id not in (select customer_id
	from Orders where product_name='C') and
	customer_id  in (select customer_id
	from Orders where product_name='A') and
	customer_id  in (select customer_id
	from Orders where product_name='B') 

1454.活跃用户

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
自连接
思路:针对a表的日期,找出日期差在0-4之间的所以b表中的行,如果不重复的日期行=5行,那说明是连续五天登陆。

select id,name
from Accounts
where id in (select a.id
from Logins a left join Logins b
on a.id=b.id and datediff(a.login_date,b.login_date) between 0 and 4
group by a.id,a.login_date
having count(distinct b.login_date)=5)
order by id
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值