牛客网sql练习笔记(四)

由于下列题目是系列题由简单到难,所以我把它们按原来顺序,全写下来了

第72题 考试分数(一)

描述

成绩表(grade),如下:
牛客网sql练习笔记(四)_第1张图片
第1行表示用户id为1的用户选择了C++岗位并且考了11001分
。。。。。。
第8行表示用户id为8的用户选择了JS岗位并且考了9999分
查询各个岗位分数的平均数,并且按照分数降序排序,结果保留小数点后面3位(3位之后四舍五入):

解答

select job,round(avg(score),3) avg
from grade
group by job
order by avg desc

第73题 考试分数(二)

描述

分数表同上,查询用户分数大于其所在工作(job)分数的平均分的所有grade的属性,并且以id的升序排序,如下:
牛客网sql练习笔记(四)_第2张图片

解答

SELECT a.id,a.job,a.score
FROM (SELECT *,avg(score)over(Partition by job ) as avg from grade) a
where score > avg

第74题 考试分数(三)

描述

企业笔试的时候,企业一般都会有不同的语言岗位,比如C++工程师,JAVA工程师,Python工程师,每个用户笔试完有不同的分数,现在有一个分数(grade)表简化如下:
牛客网sql练习笔记(四)_第3张图片
不同的语言岗位(language)表简化如下:
牛客网sql练习笔记(四)_第4张图片
请你找出每个岗位分数排名前2名的用户,得到的结果先按照language的name升序排序,再按照积分降序排序,最后按照grade的id升序排序,得到结果如下:
牛客网sql练习笔记(四)_第5张图片

解答

SELECT g.id,l.name,g.score
from(SELECT *,DENSE_RANK()over(partition by language_id order by score desc) as rn
    from grade) g 
join language l 
on g.language_id = l.id
where rn <= 2
order by l.name,g.score desc,g.id

由于是分数排名前两位,所以用连续排名dense_rank()

第75题 考试分数(四)

描述

牛客每次考试完,都会有一个成绩表(grade),如下:
牛客网sql练习笔记(四)_第6张图片
查询各个岗位分数升序排列之后的中位数位置的范围,并且按job升序排序,结果如下:
牛客网sql练习笔记(四)_第7张图片

解答

有两种解法
第一种:分情况讨论,分为奇数时,偶数时

SELECT job
        ,case when count(score)%2=0 then ceiling(count(score)/2) 
            else ceiling(count(score)/2)
        end as start1
        ,case when count(score)%2=0 then ceiling(count(score)/2+1) 
            else ceiling(count(score)/2)
        end as end1
FROM grade
GROUP BY job
ORDER BY job;

第二种:大神解法

SELECT job,
    floor(( count(*) + 1 )/ 2 ) AS "start",
    floor(( count(*) + 2 )/ 2 ) AS 'end'
FROM grade
GROUP BY job
ORDER BY job

第76题 考试分数(五)

描述

成绩表(grade),如下:
牛客网sql练习笔记(四)_第8张图片
查询各个岗位分数的中位数位置上的所有grade信息,并且按id升序排序,结果如下:
牛客网sql练习笔记(四)_第9张图片

解答

两种解法
第一种:

  1. 用上一题方法找到中位数所在位置
  2. 给原本表格加排序列
  3. 排序列值=中位数位置
SELECT a.* from (
    SELECT *,ROW_NUMBER()over(partition by job order by score desc) as t_rank
    FROM grade) a
    WHERE (a.job,a.t_rank) in (
        SELECT g1.job,
            floor(( count(*) + 1 )/ 2 ) AS 'rank'
        FROM grade g1
        GROUP BY job
        UNION
        SELECT g2.job,
            floor(( count(*) + 2 )/ 2 ) AS 'rank'
        FROM grade g2
        GROUP BY job)
ORDER BY id 

第二种:大神解法,|(排名-总数/2)|<1是中位数

select id,job,score,s_rank
from 
(select *
        ,(row_number()over(partition by job order by score desc))as s_rank
        ,(count(score)over(partition by job))as num
        from grade)t1
where abs(t1.s_rank-(t1.num+1)/2)<1
order by id;

第77题 牛客的课程订单分析(一)

描述

订单信息表(order_info),简况如下:
牛客网sql练习笔记(四)_第10张图片
查询在2025-10-15以后状态为购买成功的C++课程或者Java课程或者Python的订单,并且按照order_info的id升序排序,以上例子查询结果如下:
牛客网sql练习笔记(四)_第11张图片

解答

SELECT * from order_info 
where date > '2025-10-15' and status ='completed' 
    and product_name in ('C++','Python','Java')
order by id

第78题 牛客的课程订单分析(二)

描述

订单信息表(order_info),简况如下:
牛客网sql练习笔记(四)_第12张图片
查询在2025-10-15以后,同一个用户下单2个以及2个以上状态为购买成功的C++课程或Java课程或Python课程的user_id,并且按照user_id升序排序,以上例子查询结果如下:
牛客网sql练习笔记(四)_第13张图片

解答

SELECT user_id from order_info 
where date > '2025-10-15' and status ='completed' 
    and product_name in ('C++','Python','Java')
group by user_id
having count(1) >=2
order by user_id

第79题 牛客的课程订单分析(三)

描述

订单信息表(order_info),简况如下:
牛客网sql练习笔记(四)_第14张图片
查询在2025-10-15以后,同一个用户下单2个以及2个以上状态为购买成功的C++课程或Java课程或Python课程的订单信息,并且按照order_info的id升序排序,以上例子查询结果如下:
牛客网sql练习笔记(四)_第15张图片

解答

方法一:用上一题找到的user_id 加上其他条件

select * from order_info 
where user_id in(
        SELECT user_id from order_info 
        where date > '2025-10-15' and status ='completed' 
            and product_name in ('C++','Python','Java')
        group by user_id
        having count(1) >=2)
    and date > '2025-10-15' and status ='completed' 
    and product_name in ('C++','Python','Java')

方法二:用窗口函数

SELECT a.id,a.user_id,a.product_name,a.status,a.client_id,a.date
from(
    select *,count(id)over(partition by user_id) as c
    from order_info
    where date > '2025-10-15' 
        and status ='completed' 
        and product_name in ('C++','Python','Java')
    ) a 
where c>=2
order by a.id

第80题 牛客的课程订单分析(四)

描述

订单信息表(order_info),简况如下:
牛客网sql练习笔记(四)_第16张图片
查询在2025-10-15以后,如果有一个用户下单2个以及2个以上状态为购买成功的C++课程或Java课程或Python课程,那么输出这个用户的user_id,以及满足前面条件的第一次购买成功的C++课程或Java课程或Python课程的日期first_buy_date,以及购买成功的C++课程或Java课程或Python课程的次数cnt,并且输出结果按照user_id升序排序,以上例子查询结果如下:
牛客网sql练习笔记(四)_第17张图片

解答

select a.user_id,min(date) first_buy_date,a.cnt
from(
      select *,count(id)over(partition by user_id) as cnt
      from order_info
      where date > '2025-10-15' 
          and status ='completed' 
          and product_name in ('C++','Python','Java')) a
where a.cnt >= 2
group by a.user_id
order by a.user_id

第81题 牛客的课程订单分析(五)

描述

订单信息表(order_info),简况如下:
牛客网sql练习笔记(四)_第18张图片
查询在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升序排序,以上例子查询结果如下:
牛客网sql练习笔记(四)_第19张图片

解答

select a.user_id, min(a.date) as first_buy_date,
       max(a.date) as second_buy_date, a.cnt
from(select user_id,date,
         row_number() over(partition by user_id order by date) as rank_no,
         count(*) over(partition by user_id) as cnt
     from order_info
     where date>='2025-10-16'
      and status='completed'
      and product_name in('C++','Java','Python')
    ) a
where a.rank_no<=2 and a.cnt>=2
group by a.user_id
order by a.user_id 

第83题 牛客的课程订单分析(七)

描述

有一个订单信息表(order_info),简况如下:
牛客网sql练习笔记(四)_第20张图片
有一个客户端表(client),简况如下:
牛客网sql练习笔记(四)_第21张图片
查询在2025-10-15以后,同一个用户下单2个以及2个以上状态为购买成功的C++课程或Java课程或Python课程的来源信息,第一列是显示的是客户端名字,如果是拼团订单则显示GroupBuy,第二列显示这个客户端(或者是拼团订单)有多少订单,最后结果按照第一列(source)升序排序,以上例子查询结果如下:
牛客网sql练习笔记(四)_第22张图片

解答

SELECT (case when b.is_group_buy ='No' then c.name else 'GroupBuy' end) source,
        count(1)
from(
    select *
    from(
        select *,count(oi.id)over(partition by user_id) as cnt
        from order_info oi
        where date > '2025-10-15' 
            and status ='completed' 
            and product_name in ('C++','Python','Java')
         ) a 
    where a.cnt>=2) b
left join client c
on c.id = b.client_id
group by source
order by source

第84题 实习广场投递简历分析(一)

描述

简历信息表(resume_info),部分信息简况如下:
牛客网sql练习笔记(四)_第23张图片
查询在2025年内投递简历的岗位和数量,并且按数量降序排序,以上例子查询结果如下:
牛客网sql练习笔记(四)_第24张图片

解答

select job,sum(num) cnt
from resume_info
where date like '2025%'
group by job
order by cnt desc

第85题 实习广场投递简历分析(二)

描述

简历信息表(resume_info),部分信息简况如下:
牛客网sql练习笔记(四)_第25张图片查询在2025年内投递简历的每个岗位,每一个月内收到简历的数量,并且按先按月份降序排序,再按简历数目降序排序,以上例子查询结果如下:
牛客网sql练习笔记(四)_第26张图片

解答

方法一

select job,left(date,7) mon,sum(num) cnt
from resume_info
where date like'2025%'
group by job,mon 
order by mon desc,cnt desc

方法二:
日期函数格式转换
DATE_FORMAT(date,format)
DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据。

  • date 参数是合法的日期
  • format 规定日期/时间的输出格式
    牛客网sql练习笔记(四)_第27张图片
select job,DATE_FORMAT(date,"%Y-%m") mon,sum(num) cnt
from resume_info
where date like'2025%'
group by job,mon 
order by mon desc,cnt desc

第86题 实习广场投递简历分析(三)

描述

简历信息表(resume_info),部分信息简况如下:
牛客网sql练习笔记(四)_第28张图片
查询在2025年投递简历的每个岗位,每一个月内收到简历的数目,和对应的2026年的同一个月同岗位,收到简历的数目,最后的结果先按first_year_mon月份降序,再按job降序排序显示,以上例子查询结果如下:
牛客网sql练习笔记(四)_第29张图片

解答

SELECT h1.job,first_year_mon,first_year_cnt,second_year_mon,second_year_cnt
FROM
-- 2025年的
(SELECT job,DATE_FORMAT(DATE,'%Y-%m') AS first_year_mon,
		SUM(num) AS first_year_cnt
FROM resume_info
WHERE DATE LIKE '2025%'
GROUP BY job,first_year_mon) AS h1
JOIN
-- 2026年的
(SELECT job,DATE_FORMAT(DATE,'%Y-%m') AS second_year_mon,
		SUM(num) AS second_year_cnt
FROM resume_info
WHERE DATE LIKE '2026%'  -- 符合最左前缀匹配原则,也走索引
GROUP BY job,second_year_mon) AS h2 
-- 表连接条件:两表job相同且月份相同,
--  DATE_FORMAT()变成字符串,使用right()函数取后两位即为月数
ON h1.job=h2.job AND  right(first_year_mon,2)=right(second_year_mon,2)
ORDER BY first_year_mon DESC,h1.job DESC;

第87题 最差是第几名(一)

描述

每个人的综合成绩用A,B,C,D,E表示,90分以上都是A,8090分都是B,6070分为C,50~60为D,E为50分以下
假设每个名次最多1个人,比如有2个A,那么必定有1个A是第1名,有1个A是第2名(综合成绩同分也会按照某一门的成绩分先后)。
每次SQL考试完之后,老师会将班级成绩表展示给同学看。
现在有班级成绩表(class_grade)如下:
牛客网sql练习笔记(四)_第30张图片
查询,如果一个学生知道了自己综合成绩以后,最差是排第几名? 结果按照grade升序排序,以上例子查询如下:
牛客网sql练习笔记(四)_第31张图片

解答

select grade,sum(number)over(order by grade)
from class_grade
group by grade

第88题 最差是第几名(二)

描述

每个人的综合成绩用A,B,C,D,E表示,90分以上都是A,8090分都是B,6070分为C,50~60为D,E为50分以下
假设每个名次最多1个人,比如有2个A,那么必定有1个A是第1名,有1个A是第2名(综合成绩同分也会按照某一门的成绩分先后)。
每次SQL考试完之后,老师会将班级成绩表展示给同学看。
现在有班级成绩表(class_grade)如下:
牛客网sql练习笔记(四)_第32张图片
老师想知道学生们综合成绩的中位数是什么档位,请你写SQL帮忙查询一下,如果只有1个中位数,输出1个,如果有2个中位数,按grade升序输出,以上例子查询结果如下:
牛客网sql练习笔记(四)_第33张图片

解答

某一数的正序和逆序累计均大于整个序列的数字个数的一半即为中位数

select grade
from
    (select grade,
    (select sum(number) from class_grade) as total,
    sum(number)over(order by grade) a, -- 求正序
    sum(number)over(order by grade desc) b  -- 求逆序
     from class_grade
    order by grade)t
where a >= total/2 and b >= total/2  -- 正序逆序均大于整个数列数字个数的一半
order by grade;

第89题 获得积分最多的人(一)

描述

牛客每天有很多用户刷题,发帖,点赞,点踩等等,这些都会记录相应的积分。
有一个用户表(user),简况如下:
牛客网sql练习笔记(四)_第34张图片
还有一个积分表(grade_info),简况如下:
牛客网sql练习笔记(四)_第35张图片
查找积分增加最高的用户的名字,以及他的总积分是多少(此题数据保证积分最高的用户有且只有1个),以上例子查询结果如下:
牛客网sql练习笔记(四)_第36张图片

解答

select u.name,
       sum(case when type = 'add' then grade_num else -(grade_num) end) grade_sum
from grade_info g
join user u
on u.id = g.user_id
group by u.name
order by grade_sum desc
limit 1

第90题 获得积分最多的人(二)

描述

牛客每天有很多用户刷题,发帖,点赞,点踩等等,这些都会记录相应的积分。
有一个用户表(user),简况如下:
牛客网sql练习笔记(四)_第37张图片
还有一个积分表(grade_info),简况如下:
牛客网sql练习笔记(四)_第38张图片
查找积分增加最高的用户的id(可能有多个),名字,以及他的总积分是多少,查询结果按照id升序排序,以上例子查询结果如下:
牛客网sql练习笔记(四)_第39张图片

解答

select u.id,u.name,grade_sum
from(
	#根据总积分排序
    select a.*,rank()over(order by grade_sum desc) r
    from(
    	#算出每个人的总积分
        select g.user_id,
               sum(case when type = 'add' then grade_num else -(grade_num) end) grade_sum
        from grade_info g
        group by user_id) a) b 
join user u 
on u.id = b.user_id
where r = 1
order by u.id

你可能感兴趣的:(SQL学习笔记,sql,python,数据库)