牛客网数据库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--

相关文章
|
13天前
|
SQL 缓存 监控
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
本文详细解析了数据库、缓存、异步处理和Web性能优化四大策略,系统性能优化必知必备,大厂面试高频。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
|
24天前
|
SQL 关系型数据库 数据库
国产数据实战之docker部署MyWebSQL数据库管理工具
【10月更文挑战第23天】国产数据实战之docker部署MyWebSQL数据库管理工具
84 4
国产数据实战之docker部署MyWebSQL数据库管理工具
|
15天前
|
存储 SQL 数据库
深入浅出后端开发之数据库优化实战
【10月更文挑战第35天】在软件开发的世界里,数据库性能直接关系到应用的响应速度和用户体验。本文将带你了解如何通过合理的索引设计、查询优化以及恰当的数据存储策略来提升数据库性能。我们将一起探索这些技巧背后的原理,并通过实际案例感受优化带来的显著效果。
31 4
|
14天前
|
SQL 存储 Linux
从配置源到数据库初始化一步步教你在CentOS 7.9上安装SQL Server 2019
【11月更文挑战第8天】本文介绍了在 CentOS 7.9 上安装 SQL Server 2019 的详细步骤,包括系统准备、配置安装源、安装 SQL Server 软件包、运行安装程序、初始化数据库以及配置远程连接。通过这些步骤,您可以顺利地在 CentOS 系统上部署和使用 SQL Server 2019。
|
15天前
|
SQL 存储 Linux
从配置源到数据库初始化一步步教你在CentOS 7.9上安装SQL Server 2019
【11月更文挑战第7天】本文介绍了在 CentOS 7.9 上安装 SQL Server 2019 的详细步骤,包括系统要求检查与准备、配置安装源、安装 SQL Server 2019、配置 SQL Server 以及数据库初始化(可选)。通过这些步骤,你可以成功安装并初步配置 SQL Server 2019,进行简单的数据库操作。
|
23天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
115 1
|
25天前
|
SQL 数据采集 监控
局域网监控电脑屏幕软件:PL/SQL 实现的数据库关联监控
在当今网络环境中,基于PL/SQL的局域网监控系统对于企业和机构的信息安全至关重要。该系统包括屏幕数据采集、数据处理与分析、数据库关联与存储三个核心模块,能够提供全面而准确的监控信息,帮助管理者有效监督局域网内的电脑使用情况。
18 2
|
30天前
|
SQL JSON Java
没有数据库也能用 SQL
SPL(Structured Process Language)是一款开源软件,允许用户直接对CSV、XLS等文件进行SQL查询,无需将数据导入数据库。它提供了标准的JDBC驱动,支持复杂的SQL操作,如JOIN、子查询和WITH语句,还能处理非标准格式的文件和JSON数据。SPL不仅简化了数据查询,还提供了强大的计算能力和友好的IDE,适用于多种数据源的混合计算。
|
7天前
|
SQL 缓存 监控
SQL性能提升指南:五大优化策略与十个实战案例
在数据库性能优化的世界里,SQL优化是提升查询效率的关键。一个高效的SQL查询可以显著减少数据库的负载,提高应用响应速度,甚至影响整个系统的稳定性和扩展性。本文将介绍SQL优化的五大步骤,并结合十个实战案例,为你提供一份详尽的性能提升指南。
20 0
|
24天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
53 0
下一篇
无影云桌面