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

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

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


具体题目可参考牛客网的SQL实战模块:https://www.nowcoder.com/ta/sql?page=0


第一题:查找最晚入职员工的所有信息


select * from employeeswhere hire_date = (select max(hire_date) from employees);


解题思路:使用子查询的方法,先找出所有入职时间里最大(即最晚)的时间,这样可以确保多条最晚入职时间都可以被查询出来。


有使用order by 按由大到小排序后选取第一条的方法,但这种方法仅限于当最晚入职数据只有一条时才正确,不能保证有多条同一最晚时间时的准确性。



select * from employeesorder by hire_date desclimit 1;




第二题:查找入职员工时间排名倒数第三的员工所有信息


select * from employeeswhere hire_date = (select distinct hire_date from employeesorder by hire_date desc limit 2,1);


解题思路:同样使用子查询方法,关键是要用distinct去重,去重后会按入职日期进行分组,多个相同入职日期会分为一组。


第一次做的方法:


select * from employeesorder by hire_date desc limit 2,1;


这个查询没有去重,只能查出入职时间排名三的时间的员工信息,而不是入职员工时间排名倒数第三的员工的入职时间。




第三题:查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号dept_no


select s.*,d.dept_nofrom salaries s join dept_manager d on s.emp_no = d.emp_nowhere d.to_date = '9999-01-01' and s.to_date = '9999-01-01';


解题思路:以s.emp_no = d.emp_no为联结条件联结两表,同时限制两表to_date = '9999-01-01'(原因:去重锁定)




第四题:查找所有已经分配部门的员工的last_name和first_name


select e.last_name,e.first_name,d.dept_nofrom employees e left join dept_emp d on e.emp_no = d.emp_nowhere d.dept_no is not null;


解题思路:employees作为主表,使用左联结,关键是where d.dept_no is not null;题目要查找所有已经分配部门的员工,意味着必须要带有dept_no,没有dept_no的就是还未分配部门的,去除dept_no为空即可求得。




第五题:查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括展示没有分配具体部门的员工


select e.last_name,e.first_name,d.dept_nofrom employees e left join dept_emp d on e.emp_no = d.emp_no;


解题思路:employees作为主表,使用左联结,比较简单。




第六题:查找所有员工入职时候的薪水情况,给出emp_no以及salary, 并按照emp_no进行逆序


select e.emp_no,s.salaryfrom salaries s left join employees e on s.emp_no = e.emp_nowhere e.hire_date = s.from_dateorder by s.emp_no desc;


解题思路:使用左联结(内联结也可以),此题最关键的是salaries表的from_date 和 employees表的hire_date 的值应该要相等,因此有限制条件e.hire_date = s.from_date,两个date都是刚入职的时间,一开始我就是搞不清这个逻辑关系,一个劲想用min(from_date)求出。


另外,salaries表中有多个相同emp_no的salary,即emp_no在salaries表中不唯一,仔细查看时间和工资,推断出是同一员工在不同时间的工资不同,即涨薪或降薪(具体涨薪或降薪没有一个个查看),理解这两个关键点解题就没问题了。




第七题:查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t


select a.emp_no,count(*) tfrom salaries a inner join salaries b on a.emp_no=b.emp_no and a.to_date = b.from_datewhere a.salary < b.salarygroup by a.emp_nohaving t > 15;



解题思路:count(*) 为计算全部数据的行数地意思,比较关键的一个点就是联结条件a.to_date = b.from_date,这个条件限定了两个工资之比必须是相邻的,如果没有这个条件,那同一个emp_no下的任意两个salary都可以做对比,可以把这个条件去掉,对比两个查询结果,就明白了。


验证查询:创建表sa,表信息如下:


image.png


计算涨薪次数查询代码:


select a.emp_no,count(*) tfrom sa a inner join sa b on a.emp_no=b.emp_no and a.to_date = b.from_datewhere a.salary < b.salarygroup by a.emp_no;


image.png


验证无误,但还是有一个小问题,这个查询结果仅以后一次工资跟前一次工资对比,只要比前一次工资高,就算一次涨薪,而不与这“后一次”工资跟前一次之前的工资数据相比。


例如:


image.png


在原来数据的基础上增加两条数据,工资为1和3,这个数据查询出的涨薪次数就是4。


image.png


这条题目比较有争议,题意不清晰。以下是我找到正确答案之前的尝试:方法一:


select emp_no,count(salary) as tfrom salariesgroup by emp_nohaving t > 16;


但是这个会有一个问题,它只查询工资出现次数的计数,不管是加薪、降薪还是工资不变的所有情况,都会被计算进去。



方法二:


select emp_no,count(distinct salary) as tgroup by emp_nohaving t > 16;


这个也有问题,这只能计算出在没有降薪的情况下的涨薪次数,后面如果有降薪的话,就会出错。


(这两个方法都选择大于16的条件限定的原因:都是以工资出现次数为计算涨薪的,把第一次工资也计算进去了,实际上第一次工资不能纳入涨薪次数中去,所以用大于16来限定条件,达到符合题目要求的涨薪大于15次目的)




第八题:找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示


select salaryfrom salarieswhere to_date='9999-01-01'group by salaryorder by salary desc;


解题思路:关键理解对于相同的薪水只显示一次,使用分组方法对salary进行分组求得,也可以使用distinct去重的方法,但是一般数据较多时使用distinct效率相比group by 要慢,所以从性能角度考虑,应该尽量使用group by。


使用distinct方法如下:


select distinct salaryfrom salarieswhere to_date='9999-01-01'order by salary desc;




第九题:获取所有部门当前manager的当前薪水情况,给出dept_no, emp_no以及salary,当前表示to_date='9999-01-01'


SELECT d.dept_no,d.emp_no,s.salaryfrom salaries s left join dept_manager d on d.emp_no = s.emp_nowhere d.to_date = '9999-01-01' and s.to_date = '9999-01-01';


解题思路:关键点是dept_manager表的to_date和salaries表的to_date都要等于'9999-01-01',s.to_date = '9999-01-01'容易理解,限定当前时间当前工资,d.to_date = '9999-01-01'则限定在职经理,注意理解题目,有两个“当前”。




第十题:获取所有非manager的员工emp_no


select e.emp_nofrom employees e left join dept_manager d on e.emp_no = d.emp_nowhere d.dept_no is null;


解题思路:employees作为主表,使用左联结,限定条件为d.dept_no为空,选出在employees但不在dept_manager中的emp_no记录。


--end--

相关文章
|
8天前
|
SQL 人工智能 算法
【SQL server】玩转SQL server数据库:第二章 关系数据库
【SQL server】玩转SQL server数据库:第二章 关系数据库
51 10
|
8天前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
66 6
|
4天前
|
SQL 数据库
数据库SQL语言实战(二)
数据库SQL语言实战(二)
|
4天前
|
SQL 关系型数据库 数据库
【后端面经】【数据库与MySQL】SQL优化:如何发现SQL中的问题?
【4月更文挑战第12天】数据库优化涉及硬件升级、操作系统调整、服务器/引擎优化和SQL优化。SQL优化目标是减少磁盘IO和内存/CPU消耗。`EXPLAIN`命令用于检查SQL执行计划,关注`type`、`possible_keys`、`key`、`rows`和`filtered`字段。设计索引时考虑外键、频繁出现在`where`、`order by`和关联查询中的列,以及区分度高的列。大数据表改结构需谨慎,可能需要停机、低峰期变更或新建表。面试中应准备SQL优化案例,如覆盖索引、优化`order by`、`count`和索引提示。优化分页查询时避免大偏移量,可利用上一批的最大ID进行限制。
32 3
|
7天前
|
SQL 监控 数据库
数据库管理与电脑监控软件:SQL代码优化与实践
本文探讨了如何优化数据库管理和使用电脑监控软件以提升效率。通过SQL代码优化,如使用索引和调整查询语句,能有效提高数据库性能。同时,合理设计数据库结构,如数据表划分和规范化,也能增强管理效率。此外,利用Python脚本自动化收集系统性能数据,并实时提交至网站,可实现对电脑监控的实时性和有效性。这些方法能提升信息系统稳定性和可靠性,满足用户需求。
32 0
|
8天前
|
SQL 存储 数据挖掘
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
服务器数据恢复环境: 一台安装windows server操作系统的服务器。一组由8块硬盘组建的RAID5,划分LUN供这台服务器使用。 在windows服务器内装有SqlServer数据库。存储空间LUN划分了两个逻辑分区。 服务器故障&初检: 由于未知原因,Sql Server数据库文件丢失,丢失数据涉及到3个库,表的数量有3000左右。数据库文件丢失原因还没有查清楚,也不能确定数据存储位置。 数据库文件丢失后服务器仍处于开机状态,所幸没有大量数据写入。 将raid5中所有磁盘编号后取出,经过硬件工程师检测,没有发现明显的硬件故障。以只读方式将所有磁盘进行扇区级的全盘镜像,镜像完成后将所
数据库数据恢复—RAID5上层Sql Server数据库数据恢复案例
|
16天前
|
SQL 数据可视化 关系型数据库
轻松入门MySQL:深入探究MySQL的ER模型,数据库设计的利器与挑战(22)
轻松入门MySQL:深入探究MySQL的ER模型,数据库设计的利器与挑战(22)
|
16天前
|
存储 关系型数据库 MySQL
轻松入门MySQL:数据库设计之范式规范,优化企业管理系统效率(21)
轻松入门MySQL:数据库设计之范式规范,优化企业管理系统效率(21)
|
16天前
|
关系型数据库 MySQL 数据库
轻松入门MySQL:精准查询,巧用WHERE与HAVING,数据库查询如虎添翼(7)
轻松入门MySQL:精准查询,巧用WHERE与HAVING,数据库查询如虎添翼(7)
|
18天前
|
存储 关系型数据库 MySQL
数据库字符编码MySQL中使用UTF-8还是UTFB4
数据库字符编码MySQL中使用UTF-8还是UTFB4
20 0