个人提交答案汇总,part5
解答比较繁琐,有建议或好的想法欢迎评论区指出探讨=w=
1-20 答案链接在这里
21-40 答案链接在这里
41-60 答案链接在这里
61-80 答案链接在这里
81、写出一个sql语句查询在2025-10-15以后,如果有一个用户下单2个以及2个以上状态为购买成功的C++课程或Java课程或Python课程,那么输出这个用户的user_id,以及满足前面条件的第一次购买成功的C++课程或Java课程或Python课程的日期first_buy_date,以及满足前面条件的第二次购买成功的C++课程或Java课程或Python课程的日期second_buy_date,以及购买成功的C++课程或Java课程或Python课程的次数cnt,并且输出结果按照user_id升序排序
select a.user_id
,min(case when b.user_rank = '1' then b.date end) as first_buy_date
,min(case when b.user_rank = '2' then b.date end) as second_buy_date
,a.cnt
from (
select user_id, count(user_id) as cnt
from order_info
where product_name in ('C++', 'Python', 'Java') and status = 'completed'
and date > '2025-10-15'
group by user_id having count(user_id) >= 2
) a left join (
select user_id, date
,row_number() over (partition by user_id order by date) as user_rank
from order_info
where product_name in ('C++', 'Python', 'Java') and status = 'completed'
and date > '2025-10-15'
group by user_id, date
) b on a.user_id = b.user_id
group by a.user_id, a.cnt
order by a.user_id;
我的解答总是要繁琐点
本题我的思路是:a表查询购买2次以上的用户取出user_id和购买次数cnt,b表对所有用户的购买日期进行排序,两表进行关联取出第一次和第二次购买的日期进行输出
评论区其他精彩答案
select a.user_id,
min(date) as first_buy_date,
max(date) as second_buy_date,
a.cnt
from
(select user_id , date, row_number()over(partition by user_id order by date asc) r_number ,
count(id)over(partition by user_id)cnt
from order_info
where date > '2025-10-15'
and product_name in ('C++','Java','Python')
and status = 'completed')a
where a.r_number <= 2
and a.cnt >= 2
group by a.user_id , a.cnt
order by a.user_id asc;
82、写出一个sql语句查询在2025-10-15以后,同一个用户下单2个以及2个以上状态为购买成功的C++课程或Java课程或Python课程的订单id,是否拼团以及客户端名字信息,最后一列如果是非拼团订单,则显示对应客户端名字,如果是拼团订单,则显示NULL,并且按照order_info的id升序排序
select b.id
,b.is_group_buy
,case b.is_group_buy when 'No' then c.name
else NULL end as client_name
from (
select user_id
from order_info
where product_name in ('C++', 'Python', 'Java') and status = 'completed'
and date > '2025-10-15'
group by user_id having count(user_id) >= 2
) a
left join (
select id, user_id, is_group_buy, client_id
from order_info
where product_name in ('C++', 'Python', 'Java') and status = 'completed'
and date > '2025-10-15'
) b on a.user_id = b.user_id
left join (
select id, name from client
) c on b.client_id = c.id
order by b.id
评论区比较好的答案,我做了一点改动,原代码里的日期判定用的
datediff(date,“2025-10-15”)>0
select t2.id,t2.is_group_buy,t1.name as client_name
from client t1 right join
(
select *,count(id) over(partition by user_id) as number
from order_info
where date > '2025-10-15'
and status="completed"
and product_name in ("C++","Java","Python")
) t2
on t1.id=t2.client_id
where t2.number >1
order by t2.id
83、写出一个sql语句查询在2025-10-15以后,同一个用户下单2个以及2个以上状态为购买成功的C++课程或Java课程或Python课程的来源信息,第一列是显示的是客户端名字,如果是拼团订单则显示GroupBuy,第二列显示这个客户端(或者是拼团订单)有多少订单,最后结果按照第一列(source)升序排序
select case a.client_id
when '0' then 'GroupBuy'
else b.name end as source
,count(a.client_id) as cnt
from (
select user_id, client_id, count(id) over(partition by user_id) as buy_cnt
from order_info
where product_name in ('C++', 'Java', 'Python')
and date > '2025-10-15'
and status = 'completed'
) a left join client b on a.client_id = b.id
where a.buy_cnt >= 2
group by source
order by source
84、写出SQL语句查询在2025年内投递简历的岗位和数量,并且按数量降序排序
select job
,sum(num) as cnt
from resume_info
where left(date, 4) = '2025'
group by job
order by sum(num) desc
这里我使用的是left求年份,其实也可以用year
85、写出SQL语句查询在2025年内投递简历的每个岗位,每一个月内收到简历的数量,并且按先按月份降序排序,再按简历数目降序排序
select a.job
,case length(a.month)
when '1' then concat('2025-0',a.month)
else concat('2025-',a.month) end as mon
,a.cnt
from (
select job
,month(date) as month
,sum(num) as cnt
from resume_info where year(date) = '2025'
group by job, month(date)
order by month(date) desc, sum(num) desc
) a
这道题输出偷巧了,用的concat拼接,真是太丢人了
常用格式 | 对应描述 |
---|---|
%Y | –年,4 位 |
%m | –月,数值(00-12 |
%M | –月名 |
%k | –小时(0-23) |
评论区精彩代码
-- 按月统计数量并排序
select job,date_format(date,'%Y-%m') as mon,sum(num) as cnt
from resume_info
where date like '2025%' -- 符合最左前缀匹配原则,也走索引
group by job,mon
order by mon desc,cnt desc;
86、写出SQL语句查询在2025年投递简历的每个岗位,每一个月内收到简历的数目,和对应的2026年的同一个月同岗位,收到简历的数目,最后的结果先按first_year_mon月份降序,再按job降序排序显示
select a.job
,a.month as first_year_mon
,a.cnt as first_year_cnt
,b.month as second_year_mon
,b.cnt as second_year_cnt
from (
select job
,date_format(date,'%Y-%m') as month
,sum(num) as cnt
from resume_info
where year(date) = '2025'
group by job, month
) a,
(select job
,date_format(date,'%Y-%m') as month
,sum(num) as cnt
from resume_info
where year(date) = '2026'
group by job, month
) b
where a.job = b.job and right(a.month, 2) = right(b.month, 2)
order by first_year_mon desc, job desc;
87、写出一个SQL查询,如果一个学生知道了自己综合成绩以后,最差是排第几名? 结果按照grade升序排序
select grade
,(select sum(number) from class_grade b
where a.grade >= b.grade
) as t_rank
from class_grade a
order by grade;
这个也有其他解法,用sum() over()
select grade
,sum(number) over(order by grade) as t_rank
from class_grade a
order by grade;
sum(…) over( ),对所有行求和
sum(…) over( order by … ), 连续求和
sum(…) over( partition by… ),同组内所行求和
sum(…) over( partition by… order by … ),同第1点中的排序求和原理,只是范围限制在组内
(sum() over() 参考文章:https://blog.csdn.net/imliuqun123/article/details/80063827)
88、老师想知道学生们综合成绩的中位数是什么档位,请你写SQL帮忙查询一下,如果只有1个中位数,输出1个,如果有2个中位数,按grade升序输出
没写出来···直接看评论区精彩代码
select grade from
(select *, (tb1.ed - tb1.number) st, sum(number) over() tp
from
(select *, sum(number) over(order by grade) ed
from class_grade) tb1
) tb2
where tp/2 between st and ed;
最内层嵌套:
内层嵌套:
tp/2 between st and ed这个条件用的很绝,这个题解可以记下。
89、写一个SQL查找积分增加最高的用户的名字,以及他的总积分是多少(此题数据保证积分最高的用户有且只有1个)
select user.name
,b.num
from (
select distinct a.user_id
,sum(a.grade_num) over(partition by a.user_id) as num
from grade_info a join user b on a.user_id = b.id
where a.type = 'add' order by num desc
limit 1
) b, user
where user.id = b.user_id
90、写一个SQL查找积分增加最高的用户的id(可能有多个),名字,以及他的总积分是多少,查询结果按照id升序排序
select tb1.user_id
,user.name
,tb1.sum_num as grade_sum
from (
select user_id
,sum(grade_num) as sum_num
from grade_info
group by user_id
) tb1,(
select max(a.num) as sum_num
from (
select user_id
,sum(grade_num) as num
from grade_info
where type = 'add'
group by user_id
) a
) tb2, user
where tb1.sum_num = tb2.sum_num
and tb1.user_id = user.id
提交之后想到dense_rank也可以用来排序就试了试,ac,这个解法更简单些。
select a.user_id as id
,b.name as name
,a.num as grade_sum
from (
select user_id
,sum(grade_num) as num
,dense_rank() over(order by sum(grade_num) desc ) as d_rank
from grade_info
where type = 'add'
group by user_id
) a, user b
where a.user_id = b.id
and a.d_rank = '1'
91、写一个SQL查找积分最高的用户的id,名字,以及他的总积分是多少(可能有多个),查询结果按照id升序排序
select b.user_id
,user.name
,b.num
from (
select a.*, dense_rank() over(order by a.num desc) as d_rank
from (select ad.user_id
,case
when re.sum is NULL then ad.sum
else (ad.sum - re.sum) end as num
from (
select user_id, sum(grade_num) as sum
from grade_info where type = 'add' group by user_id
) ad left join (
select user_id, sum(grade_num) as sum
from grade_info where type = 'reduce' group by user_id
) re on ad.user_id = re.user_id
) a
) b, user
where b.user_id = user.id and b.d_rank = '1'
我是将add和reduce的分值单独查询之后加总,评论区发现了更简洁的写法,if的用法还是很重要的!
select id, name, grade_sum
from(select user_id, grade_sum, rank() over(order by grade_sum desc) ranking
from(select user_id, sum(if(type = 'add', grade_num, -grade_num)) grade_sum
from grade_info
group by user_id) n1) n2
join user
on n2.user_id = user.id
where ranking = 1
order by id
okk!牛客的题终于刷完了!完结!