暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

按在地上摩擦面试官mysql之实战七

Java八股文宝典 2021-04-20
303

日常工作中,会遇到大量的sql编写,同样一个逻辑,每个人写的sql会有不同。实战篇会带领大家进行大量的sql练习,希望你自己独立思考,进行sql编写

Q1

考试分数(一)


牛客每次考试完,都会有一个成绩表(grade),如下:


第1行表示用户id为1的用户选择了C++岗位并且考了11001分

。。。

第8行表示用户id为8的用户选择了JS岗位并且考了9999分


请你写一个sql语句查询各个岗位分数的平均数,并且按照分数降序排序,结果保留小数点后面3位(3位之后四舍五入)


01

考试分数(一)

自己思考几分钟,在看下我的思路:

点击空白处查看答案

1. 聚合操作利用group by配合avg

2. round(n,m) n数值,m保留几位有效数字


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

 

Q2

考试分数(二) 


牛客每次考试完,都会有一个成绩表(grade),如下:


第1行表示用户id为1的用户选择了C++岗位并且考了11001分

。。。

第8行表示用户id为8的用户选择了JS岗位并且考了9999分


请你写一个sql语句查询用户分数大于其所在工作(job)分数的平均分的所有grade的属性,并且以id的升序排序


02

考试分数(二) 

自己思考几分钟,在看下我的思路:

点击空白处查看答案

1. 先找到每个job的平均分

2. 关联比较同一job分数大于平均分的



select g.id, g.job, score from grade g join (select job, avg(score) avg1 from grade group by job)s

on g.job = s.job

where score > avg1

order by id


 

Q3

 考试分数(三) 


牛客每次举办企业笔试的时候,企业一般都会有不同的语言岗位,比如C++工程师,JAVA工程师,Python工程师,每个用户笔试完有不同的分数,现在有一个分数(grade)表简化如下:


第1行表示用户id为1的选择了language_id为1岗位的最后考试完的分数为12000,
....
第7行表示用户id为7的选择了language_id为2岗位的最后考试完的分数为11000,

不同的语言岗位(language)表简化如下:


请你找出每个岗位分数排名前2名的用户,得到的结果先按照language的name升序排序,再按照积分降序排序,最后按照grade的id升序排序,得到结果如下:


03

 考试分数(三) 

自己思考几分钟,在看下我的思路:

点击空白处查看答案

1. 利用窗口函数 dense_rank() over

2. 关联language找到name

3. 将上面的结果作为临时表,取前两名添加rn条件<3


select id,name,score

from (select g.id,l.name,g.score,

dense_rank() over(partition by g.language_id order by score desc) rn from

grade g inner join language l on g.language_id=l.id) t

where rn<3

order by name,score desc,id;


 

Q4

考试分数(四) 


牛客每次考试完,都会有一个成绩表(grade),如下:


第1行表示用户id为1的用户选择了C++岗位并且考了11001分

。。。

第8行表示用户id为8的用户选择了JS岗位并且考了9999分


请你写一个sql语句查询各个岗位分数升序排列之后的中位数位置的范围,并且按job升序排序


04

考试分数(四) 

自己思考几分钟,在看下我的思路:

点击空白处查看答案

1. 此题是一道数学题,知道中位数,那么sql自然而然就会写了

2. 假设1个岗位人数总数为N,那么不管是奇数还是偶数,起始位置一定是N/2

3. 如果是奇数,那么终止位置也是N/2,如果是偶数,终止位置就是N/2+1,所以后面的+1判断是不是偶数就行了


select job,floor((count(id)+1)/2) as 'start',ceil((count(id)+1)/2) as 'end'

from grade

group by job

order by job asc


 

Q5

考试分数(五)


牛客每次考试完,都会有一个成绩表(grade),如下:


第1行表示用户id为1的用户选择了C++岗位并且考了11001分

。。。

第8行表示用户id为8的用户选择了JS岗位并且考了9999分


请你写一个sql语句查询各个岗位分数的中位数位置上的所有grade信息,并且按id升序排序


05

考试分数(五)

自己思考几分钟,在看下我的思路:

点击空白处查看答案

1. 中位数本身就是先按自然数排名,再取数。排序函数选用row_number

2. 用一条规则统一奇数个数时和偶数个数时的中位数位置。无论奇偶,中位数的位置距离(个数+1)/2 小于1


select id,job,score,r from

(select *,rank()over(partition by job order by score desc)as r,count(*)over(partition by job)as t

from grade) as A

where round(abs(r-(t+1)/2)*1.0,2)<1

order by id;


 

Q6

最差是第几名(一)


TM小哥和FH小妹在牛客大学若干年后成立了牛客SQL班,班的每个人的综合成绩用A,B,C,D,E表示,90分以上都是A,80~90分都是B,60~70分为C,50~60为D,E为50分以下

因为每个名次最多1个人,比如有2个A,那么必定有1个A是第1名,有1个A是第2名(综合成绩同分也会按照某一门的成绩分先后)。

每次SQL考试完之后,老师会将班级成绩表展示给同学看。

现在有班级成绩表(class_grade)如下


第1行表示成绩为A的学生有2个

.......

最后1行表示成绩为B的学生有2个


请你写出一个SQL查询,如果一个学生知道了自己综合成绩以后,最差是排第几名? 结果按照grade升序排序


06

最差是第几名(一)

自己思考几分钟,在看下我的思路:

点击空白处查看答案

1. over窗口函数的使用


select grade,

sum(number)

over(order by grade) t_rank

from class_grade;


 

Q7

 最差是第几名(二)


TM小哥和FH小妹在牛客大学若干年后成立了牛客SQL班,班的每个人的综合成绩用A,B,C,D,E表示,90分以上都是A,80~90分都是B,60~70分为C,50~60为D,E为50分以下

因为每个名次最多1个人,比如有2个A,那么必定有1个A是第1名,有1个A是第2名(综合成绩同分也会按照某一门的成绩分先后)。

每次SQL考试完之后,老师会将班级成绩表展示给同学看。

现在有班级成绩表(class_grade)如下


第1行表示成绩为A的学生有2个

.......

最后1行表示成绩为B的学生有2个


老师想知道学生们综合成绩的中位数是什么档位,请你写SQL帮忙查询一下,如果只有1个中位数,输出1个,如果有2个中位数,按grade升序输出 


07

 最差是第几名(二)

自己思考几分钟,在看下我的思路:

点击空白处查看答案

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

A A B B C C D D 

1 2 3  4  5 6  7 8

8 7 6  5  4  3 2 1

那么上面的4,5以及5,4就是中位数,如果是奇数的话,就只有1个

2. 求逆序和其实就是 sum(a) over (order by b desc) 就行了,多加了一个desc


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) t1

where a >= total/2 and b >=total/2

order by grade


 

Q8

获得积分最多的人(一)


牛客每天有很多用户刷题,发帖,点赞,点踩等等,这些都会记录相应的积分。

有一个用户表(user)


还有一个积分表(grade_info),简况如下

第1行表示,user_id为1的用户积分增加了3分。

第2行表示,user_id为2的用户积分增加了3分。

第3行表示,user_id为1的用户积分又增加了1分。

.......

最后1行表示,user_id为5的用户积分增加了3分。


请你写一个SQL查找积分增加最高的用户的名字,以及他的总积分是多少(此题数据保证积分最高的用户有且只有1个)


08

获得积分最多的人(一)

自己思考几分钟,在看下我的思路:

点击空白处查看答案

1. 分组,求和,倒序取一条


select u.name, sum(g.grade_num) as s

from user u

inner join grade_info g

on u.id = g.user_id

group by u.name

order by s desc

limit 1;


 

Q9

获得积分最多的人(二)


牛客每天有很多用户刷题,发帖,点赞,点踩等等,这些都会记录相应的积分。

有一个用户表(user)

还有一个积分表(grade_info),简况如下


第1行表示,user_id为1的用户积分增加了3分。

第2行表示,user_id为2的用户积分增加了3分。

第3行表示,user_id为1的用户积分又增加了1分。

.......

最后1行表示,user_id为5的用户积分增加了3分。


请你写一个SQL查找积分增加最高的用户的id(可能有多个),名字,以及他的总积分是多少,查询结果按照id升序排序


09

获得积分最多的人(二)

自己思考几分钟,在看下我的思路:

点击空白处查看答案

1. 根据上题我们能轻松的找到最大的积分总和

2. 再根据最大积分总和找到对应的user_id和总积分 group by 不能跟where

3. 再关联user表找name




select user.id, user.name,t.grade_sum from(

select user_id,sum(grade_num) as grade_sum from grade_info group by user_id

having grade_sum=(select sum(grade_num) as s from grade_info group by user_id order by s desc limit 1)

) t

join user

on t.user_id=user.id

order by user.id  


 

Q10

获得积分最多的人(三)


牛客每天有很多用户刷题,发帖,点赞,点踩等等,这些都会记录相应的积分。

有一个用户表(user)

还有一个积分表(grade_info),简况如下

第1行表示,user_id为1的用户积分增加了3分。

第2行表示,user_id为2的用户积分增加了3分。

第3行表示,user_id为1的用户积分又增加了1分。

.......

最后1行表示,user_id为5的用户积分增加了3分。


请你写一个SQL查找积分增加最高的用户的id,名字,以及他的总积分是多少(可能有多个),查询结果按照id升序排序


10

获得积分最多的人(三)

自己思考几分钟,在看下我的思路:

点击空白处查看答案

1. 与前一题基本差不多,唯一不同就是分数的计算

2. 使用case when判断分数是加还是减


select user.id, user.name,t.grade_sum from(

select user_id,sum(case type when 'add' then grade_num else -grade_num end) as grade_sum from grade_info group by user_id

having grade_sum=(select sum(case type when 'add' then grade_num else -grade_num end ) as grade_sum from grade_info group by user_id order by grade_sum desc limit 1)

) t

join user

on t.user_id=user.id

order by user.id


 

OS:每天坚持跟山虎做十道题,几天之后你的sql功底就会突飞猛进。

大家好,我是山虎,喜欢数学,编码,算法,股票,AI。经历过一次失败的创业。东西不要死记硬背,要做到自己真正的理解。年轻人就要折腾,年轻人就要折腾,年轻人就要折腾。原创不易,帮忙转发。

JAVA八股文

随时欢迎与我讨论各种问题

文章转载自Java八股文宝典,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论