牛客网数据库SQL实战详细剖析(11-20)

牛客网数据库SQL实战详细剖析(11-20)_第1张图片

本文授权转载自大数据肌肉猿

禁止二次转载

大家好,我是老表

阅读文本大概需要 11 分钟

这是一个系列文章,总共61题,分6期,有答案以及解题思路,并附上解题的一个思考过程。

具体题目可参考牛客网的SQL实战模块:

https://www.nowcoder.com/ta/sql?page=0

系列文章

1、牛客网数据库SQL实战详细剖析(1-10)

第十一题:获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date='9999-01-01'。

结果第一列给出当前员工的emp_no,第二列给出其manager对应的manager_no。

SELECT  de.emp_no,  dm.emp_no AS manager_no FROM  dept_emp deLEFT JOIN dept_manager dm ON de.dept_no = dm.dept_no WHERE  de.to_date = '9999-01-01'AND dm.to_date = '9999-01-01'AND de.emp_no <> dm.emp_no;

解题思路:重点要理解两表之间的逻辑关系和题目要求。有三个关键点:

①每个部门都有一个manager 每个人都有自己所在的部门。所以用部门号dept_no作为联结条件,左联结和内联结都可以;

②如果员工当前的manager是自己的话结果不显示,这就要求dept_emp表的员工编号emp_no和dept_manager的员工编号不相等;

③题目要求当前的manager,所以最后的经理表dept_manager的时间为to_date='9999-01-01',严谨起见,员工表dept_emp的时间也应该是to_date='9999-01-01'。

 

第十二题:获取所有部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary

SELECT  d.dept_no,  s.emp_no,max( s.salary ) AS salary FROM  salaries sLEFT JOIN dept_emp d ON s.emp_no = d.emp_no WHERE  s.to_date = '9999-01-01'AND d.to_date = '9999-01-01'GROUP BY  d.dept_no;

解题思路:

①用GROUP BY d.dept_no将每个部门分为一组,用MAX()函数选取每组中工资最高者。

②为获得当前薪水,工资表和部门表的to_date都是'9999-01-01' 。

 

第十三题:从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t

SELECT  title,count( title ) AS t FROM  titles GROUP BY  title HAVING  t >= 2;

解题思路:使用group by将title分组,再用having子句找出大于等于2的组,having必须在group by之后,并且有group by才能使用having,聚合参数也可以是count(*) 和count(emp_no) ,还要注意>=号之间不能有空格,否则会出错。

第十四题:从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。注意对于重复的emp_no进行忽略

SELECT  title,count( DISTINCT emp_no ) AS t FROM  titles GROUP BY  title HAVING  t >= 2;

解题思路:参考上题思路,同时使用distinct去重emp_no。

 

第十五题:查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列

SELECT  * FROM  employees WHERE  emp_no % 2 = 1AND last_name != 'Mary'ORDER BY  hire_date DESC;

解题思路:员工号为奇数,则emp_no取余应为1,last_name不为Mary,用‘!=’表示,另外注意字符串要用单括号括起来,逆序用desc。

 

第十六题:统计出当前各个title类型对应的员工当前(to_date='9999-01-01')薪水对应的平均工资。结果给出title以及平均工资avg。

SELECT  t.title,avg( salary ) AS avgFROM  salaries sINNER JOIN titles t ON s.emp_no = t.emp_no WHERE  s.to_date = '9999-01-01'AND t.to_date = '9999-01-01'GROUP BY  t.title;

解题思路:使用group by 对title进行分组,当前用两表to_date='9999-01-01'进行限定,平均工资用聚合函数avg。

 

第十七题:获取当前(to_date='9999-01-01')薪水第二多的员工的emp_no以及其对应的薪水salary

SELECT
  emp_no,
  salary 
FROM
  salaries 
WHERE
  salary = ( SELECT max( salary ) FROM salaries WHERE to_date = '9999-01-01' AND salary < ( SELECT max( salary ) FROM salaries ) );

解题思路:本题难点在于如何找出薪水排第二的员工,使用子查询里嵌套子查询。

①先在工资表里找出最多工资,再以工资小于最大工资为限定条件,即salary < (select max(salary)可以得到排名第二的工资。

②再使用max(salary)在除去排名第一工资的表里找最大的工资,即找到排名第二的工资。

③这个写法,不管工资第一多的员工有多少个,都能查到工资第二多的员工,且当工资第二多的员工有多个时,也都能查询出来,可以插入数据验证。

以下这种写法,尽管第一名工资有多个时仍然能查出工资第二多的,但当工资第二多的有多个员工的时候,只能查询出一个,不能查询出多个。

SELECT
  emp_no,
max( salary ) 
FROM
  salaries 
WHERE
  salary < ( SELECT max( salary ) FROM salaries ) 
AND to_date = '9999-01-01';

第十八题:查找当前薪水(to_date='9999-01-01')排名第二多的员工编号emp_no、薪水salary、last_name以及first_name,不准使用order by

SELECT  e.emp_no,  s.salary,  e.last_name,  e.first_name FROM  employees eINNER JOIN salaries s ON e.emp_no = s.emp_no WHERE  salary = ( SELECT max( salary ) FROM salaries WHERE to_date = '9999-01-01' AND salary < ( SELECT max( salary ) FROM salaries ) );

解题思路:本题只需要在上一题的基础上增加一个内联结(左联结)即可将薪水salary、last_name以及first_name查询出来。

 

第十九题:查找所有员工的last_name和first_name以及对应的dept_name,也包括暂时没有分配部门的员工

SELECT  last_name,  first_name,  dept_name FROM  (SELECT  e.last_name,  e.first_name,  de.dept_no FROM  employees eLEFT JOIN dept_emp de ON e.emp_no = de.emp_no   ) aLEFT JOIN departments dp ON a.dept_no = dp.dept_no;

解题思路:本题关键在于理清三表之间关联关系。需要使用两次左联结。红色部分可以省略。

①题目要求包括暂时没有分配部门的员工,所以将employees作为主表,使用左联结将其和dept_emp表联结,联结条件为员工编号emp_no,得出所有员工所在部门,并将结果命名为a。

②将查询结果a与departments左联结,联结条件为部门编号dept_no,求出部门名字dept_name。

 

第二十题:查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth

方法一:

SELECTmax( salary ) - min( salary ) AS growth FROM  salaries WHERE  emp_no = '10001';

方法二:

SELECT( SELECT salary FROM salaries WHERE emp_no = '10001' ORDER BY to_date DESC LIMIT 1 ) - ( SELECT salary FROM salaries WHERE emp_no = '10001' ORDER BY to_date ASC LIMIT 1 ) AS growth;FROM  salaries;

解题思路:对“入职以来的薪水salary涨幅值growth”有两种理解,第一种是员工入职以来工资最大值减去工资最小值,参考方法一。第二种理解是最新一次工资减去入职时的工资,即为涨幅值growth,参考方法二,方法二更严谨。

大家好,我是老表
觉得本文不错的话,转发、留言、点赞,是对我最大的支持。

欢迎关注微信公众号:简说Python关注后回复:1024,可以领取学习资源。

每日留言

说说你读完本文感受?

或者一句激励自己的话?

(字数不少于15字)

怎么加入习队

点我,看文末彩蛋

留言有啥福利

点我就知道了

想进学习交流

微信jjxksa888

:简说Python

既然大家非主流还用

2小时快速掌握Python基础知识要点

完整Python基础知识要点

Python小知识 | 这些技能你不会?(一)

Python小知识 | 这些技能你不会?(二)

Python小知识 | 这些技能你不会?(三)

Python小知识 | 这些技能你不会?(四)

近期推荐阅读: 【1】 整理了我开始分享学习笔记到现在超过250篇优质文章,涵盖数据分析、爬虫、机器学习等方面,别再说不知道该从哪开始,实战哪里找了

【2】【终篇】Pandas中文官方文档:基础用法6(含1-5)

觉得不错就点一下“在看”吧 

你可能感兴趣的:(牛客网数据库SQL实战详细剖析(11-20))