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

相关文章
|
1月前
|
SQL 机器学习/深度学习 人工智能
从“写SQL”到“聊数据”:NL2SQL如何用自然语言解锁数据库?
本文系统性地阐述了自然语言转SQL(NL2SQL) 技术如何让非技术背景的业务分析师实现数据自助查询,从而提升数据驱动决策的效率与准确性。
从“写SQL”到“聊数据”:NL2SQL如何用自然语言解锁数据库?
|
3天前
|
SQL 人工智能 Linux
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
62 5
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
|
2天前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
|
3天前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
20天前
|
SQL Oracle 关系型数据库
Oracle数据库创建表空间和索引的SQL语法示例
以上SQL语法提供了一种标准方式去组织Oracle数据库内部结构,并且通过合理使用可以显著改善查询速度及整体性能。需要注意,在实际应用过程当中应该根据具体业务需求、系统资源状况以及预期目标去合理规划并调整参数设置以达到最佳效果。
77 8
|
25天前
|
SQL 人工智能 Java
用 LangChain4j+Ollama 打造 Text-to-SQL AI Agent,数据库想问就问
本文介绍了如何利用AI技术简化SQL查询操作,让不懂技术的用户也能轻松从数据库中获取信息。通过本地部署PostgreSQL数据库和Ollama模型,结合Java代码,实现将自然语言问题自动转换为SQL查询,并将结果以易懂的方式呈现。整个流程简单直观,适合初学者动手实践,同时也展示了AI在数据查询中的潜力与局限。
168 8
|
1月前
|
SQL 人工智能 Linux
SQL Server 2025 RC0 发布 - 从本地到云端的 AI 就绪企业数据库
SQL Server 2025 RC0 发布 - 从本地到云端的 AI 就绪企业数据库
111 5
|
8天前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
|
2月前
|
SQL 缓存 监控
SqlRest让SQL秒变Http API,还支持20+数据库(含国产数据库)
杭州奥零数据科技有限公司成立于2023年,专注于数据中台业务,维护开源项目AllData并提供商业版解决方案。AllData提供数据集成、存储、开发、治理及BI展示等一站式服务,支持AI大模型应用,助力企业高效利用数据价值。
|
SQL Oracle 关系型数据库
本机不安装Oracle客户端,使用PL/SQL Developer连接远程数据库
本机不安装Oracle客户端,使用PL/SQL Developer连接远程数据库
581 0