SQL练习题十六-牛客网错题难题再写一遍

牛客网的题目都是截图,我懒得截图了直接标明题目,请在牛客网中查找实际序号吧...
下面的题目都是之前出于各种原因在笔记上的题目,再写一遍希望有所收获

161.获取当前薪水第二多的员工(18)

使用子查询来获取,查找出最大的薪资,然后在剩余的薪资中查找出最大的即是第二大的值
序列函数也可以

select 
employees.emp_no,salary,last_name,first_name
from 
employees join salaries on employees.emp_no = salaries.emp_no
where salary = (
select
max(salary)
from 
salaries
where salary < (select max(salary) from   salaries)
) 

162.统计各部门工资条数(22)

我为什么会记录这道题目???这道题目可以考察更多的内容,比如说涨工资的情况等

select
t1.dept_no ,t1.dept_name,count(salary) as `sum`
from
departments t1 join  dept_emp t2 on t1.dept_no = t2.dept_no
               join  salaries t3 on t2.emp_no = t3.emp_no
group by t1.dept_no ,t1.dept_name
order by t1.dept_no

163.对所有员工薪水进行排名(23)☆

自连接分数排名,使用窗口也可(rank),学习使用自连接解决窗口问题,比如说sum()开窗,使用having来过滤即可,比如这题的序列排名,还有分组topN问题,使用自连接限制where的条件即可(结合group by 分组获取的条数来判断),面试常问!!!!!!

select
t1.emp_no ,t1.salary,count(distinct t2.salary) as t_rank 
from
salaries t1 cross join salaries t2 
where t1.salary <= t2.salary
group by t1.emp_no ,t1.salary
order by t_rank

164.获取员工的薪水比其领导还高的员工相关信息(25)

第一次写的比这个复杂??第二次写还是不够好,看了一下评论区可以采用再join 一张薪水表来实现,可能速度会快一点?然而并不,不知道在大数据中哪个快一点??

select
t1.emp_no,t3.emp_no  manager_no , t2.salary  emp_salary , t3.salary  manager_salary
from
dept_emp t1 join salaries t2 on t1.emp_no = t2.emp_no
join 
(
select
dept_manager.dept_no as dept_no,salary,dept_manager.emp_no emp_no
from
dept_manager join salaries on dept_manager.emp_no = salaries.emp_no
) t3 
on t1.dept_no = t3.dept_no
where t2.salary > t3.salary
select de.emp_no, dm.emp_no as manager_no,
s1.salary as emp_salary, s2.salary as manager_salary
from dept_emp de, dept_manager dm, salaries s1, salaries s2
where de.dept_no = dm.dept_no
and de.emp_no = s1.emp_no
and dm.emp_no = s2.emp_no
and s1.salary > s2.salary

165.找出没有分类的电影id和其他信息(29)

这题我以前写错了....这题考察在left join 条件下 on where 条件的区别,on会返回没有匹配上的行(也就是说始终返回左边的数据),而where会过滤null的值,还有这题也考察了 is null != null的区别,!=null始终会返回true,所以尽量使用is (not) null

select
t1.film_id ,title
from 
film t1 left join film_category t2 on t1.film_id = t2.film_id
where category_id is null

166.删除重复emp_no的记录,只保留最小id的记录(42)

这题目在leedcode中也有学习delete语法,牛客网还有其他的DML语法练习题,注意delete在mysql中的语法,注意方法二中的表达

delete from titles_test
where id not in (
  select * from (
select
min(id)
from titles_test
group by emp_no ) l ) 
delete t1  from titles_test t1 , titles_test t2
where t1.emp_no = t2.emp_no and t1.id > t2.id

167.牛客新登录用户的次日成功的留存率(68)

对于这种留存率的问题,就是指标的处理,一般采用的函数有lag/lead,不同窗口大小下的开窗进行比较等,以后专门有一篇博客来示例这种指标值
但是这题....过于简单...就是连续登陆的变形题,序列函数即可...不用窗口更简单

select
round(count(distinct t1.user_id ) /(select count(distinct user_id) from login ) ,3)  p
from 
(
select
user_id,min(date) as date
from 
login
group by user_id
) t1 
join login on t1.user_id = login.user_id
where datediff(login.date,t1.date) =1

评论区:查询最小的天数+1 where联合查询看是否存在这一天

select 
round(count(distinct user_id)*1.0/(select count(distinct user_id) from login) ,3)
from login
where (user_id,date)
in (select user_id,DATE_ADD(min(date),INTERVAL 1 DAY) from login group by user_id);

168.统计牛客每个日期登录新用户个数(69)(窗口写法)

注意sum/count与if一起用的时候要注意0的使用count也会+1所以这里是sum,如果要使用count则应该把0改为null然后在外面嵌套一个ifnull

select
date,
sum(if(rn = 1,1,0)) new 
from 
(
select 
date,rank() over(partition by user_id order by date) rn 
from 
login
) t1
group by date

也可以使用老方法区每个人最早登录的时间然后按照时间group by ,接着获取全部的时间,不能join上的就为0

select a.all_date as date, ifnull(count(b.user_id),0) as new
from
    (select distinct(date) as all_date
    from login) as a
left join
    (select user_id, min(date) as reg_date
    from login
    group by user_id) as b 
on a.all_date = b.reg_date
group by a.all_date

169.每个日期新用户的次日留存率(70)

使用union 来代替一次join连接

(
select
t1.date ,round(count(t2.user_id) / count(t1.user_id) ,3)  p
from 
(
select
user_id,min(date) as date
from 
login
group by user_id
) t1 
left join login t2 on datediff(t1.date,t2.date) = -1  and t1.user_id = t2.user_id
group by t1.date
)
union 
select date,0.000 p from login 
where date not in (select min(date)
from login
group by user_id)
order by date
(
select
t1.date ,round(count(t2.user_id) / count(t1.user_id) ,3)  p
from 
(
select
user_id,min(date) as date
from 
login
group by user_id
) t1 
left join login t2 on DATE_SUB(t1.date,INTERVAL - 1 DAY) = t2.date  and t1.user_id = t2.user_id
group by t1.date
)
union 
select date,0.000 p from login 
where date not in (select min(date)
from login
group by user_id)
order by date

170.请你找出每个岗位分数排名前2的用户(74)

分组topN的问题,使用自连接having过滤来获取topN,二是使用窗口来求

select
grade.id,name,s1.score
from 
grade
join 
(
select
t1.language_id,t1.score
from
grade t1 join grade t2 on t1.language_id = t2.language_id and t1.score <= t2.score
group by t1.language_id,t1.score
having count(distinct t2.score) <= 2
) s1 
on grade.language_id = s1.language_id and grade.score = s1.score 
join 
language 
on grade.language_id = language.id
order by name,score desc 
select gl.id,gl.name,gl.score
from (select g.id,l.name,g.score,
dense_rank() over(partition by g.language_id order by g.score desc) as ran
from grade g  join language l
on g.language_id = l.id) gl
where gl.ran < 3
order by gl.name

171.中位数位置的范围(75)

第76同这一题都是求中位数,leedcode中也有类似的题目,使用两个序列函数来求,值得注意的是如果排两个,要排序的字段有重复的,按照字典顺序顺序和逆序会乱序,要指定第二个人字段desc/asc
这道题目之前写复杂了,直接借助于round的四舍五入来求即可..不需要使用case when 来分类讨论

select
job,round(count(score)/2) start ,round((count(score) +1) /2) end
from
grade
group by job
order by job

一些函数的使用

limit的用法 limit 1,2 从位移1截取取2个
length( '10,A,B') - length(REPLACE( '10,A,B',',',''));
--负数的使用,从后面开始查询
select 
first_name
from
employees
order by  substr(first_name,-2,2) 
--group_concat函数的使用大致等同于concat和collect_list的结合
select 
dept_no,
group_concat(emp_no)
from
dept_emp
group  by dept_no
--limit的分页功能
select *
from employees
limit 5, 5;
``
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容