MySQL基础(三)——数据查询语言DQL(二)之查询实战

前言

  我们上篇文章给大家介绍了数据库查询语言中的单表查询理论的部分,主要包括全表查询、查询指定的列、去重、条件查询、模糊查询以及对查询的结果进行分组、排序以及限制。另外介绍了MySQL中常用的聚合函数和常用的一些运算符。在文章的最后我们介绍了MySQL查询语句在书写以及执行之间的区别。查询语言是MySQL中最为重要的一部分,需要我们在日常生活中多加练习。虽然在上篇文章中介绍了一些案例,但是为了让读者对单表查询有一个更深的理解,我们通过牛客网中的一些面试真题对单表查询的内容进行巩固总结。

一、查找最晚入职员工的所有信息

1、题目描述

  有一个员工employees表简况如下:

select * from employees;

  员工employees表的信息如下:

  建表语句如下:

CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL, 
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

  请你查找employees里最晚入职员工的所有信息,以上例子输出如下:

2、题目解析

  本题其实很简单,就是简单的将employees表中的数据按日期进行降序排序,最后通过limit语句将其进行输出即可;具体用代码实现如下:

select * 
from employees 
order by hire_date desc 
limit 0,1;

  代码执行的结果如下:

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

1、题目描述

  本题的表和前面的表是一样的,这里不做过多重复阐述。我们这次需要 查找employees里入职员工时间排名倒数第三的员工所有信息。输出的结果如下:

2、题目解析

  本题和上题差不多,上题是让我们查找出入职最晚的员工信息,本题是让我们查找出入职员工中倒数第三的员工信息,还是需要对入职员工的入职日期进行降序排序,也需要对输出的结果进行限制,不过我们的相对偏移量不在是0,而是2,具体查询语句实现如下:

select * 
from employees 
order by hire_date desc 
limit 2,1;

  代码执行的结果如下:

三、查找各个部门当前领导当前薪水详情以及部门编号

1、题目描述

  有一个全部员工的薪水表salaries简况如下:

select * 
from salaries;

  全部员工的薪水表salaries的详情如下:

  有一个各个部门的领导表dept_manager简况如下:

select * 
from dept_manager;

  各个部门的领导表dept_manager详情如下:

  建表语句如下:

-- 首先建立`salaries`表:
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

-- 接着建立`dept_manager`表
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

  请你查找各个部门领导薪水详情以及其对应部门编号dept_no,输出结果以salaries.emp_no升序排序,并且请注意输出结果里面dept_no列是最后一列,以上例子输入如下:

2、题目详解

  本题是涉及到了两张表,一张是salaries表,另一张是dept_manager表,需要我们查找的字段中也是涉及到了这两张表,因此,这就有两种方法,其中一种就是用到多表连接进行查找,当然,其实只要是多表查找的我们均可以将其转化为嵌套查找,我们接下来首先介绍方法一;
  我们可以使用join关联两张表,然后再用where条件筛选进行查询,不过这里需要我们注意的是:由于多表连接有一个主键,我们在连接的时候,需要两张表的emp_no应该相等;具体语句实现入下:

select s.* ,d.dept_no
from salaries as s 
join dept_manager as d 
on s.emp_no=d.emp_no
where s.to_date = '9999-01-01' and d.to_date='9999-01-01';

  具体执行的结果如下:

  在第二种方法中,我们直接用where语句实现;具体sql语句实现如下:

select s.*, d.dept_no
from dept_manager d, salaries s
where s.emp_no = d.emp_no and s.to_date = '9999-01-01' and d.to_date = '9999-01-01'
order by s.emp_no; 

  具体执行的结果如下:

四、查找所有已分配部门的员工的last_name和first_name

1、题目描述

  有一个员工表,employees简况如下:

select *
from employees;

  employees表的详情如下:

  有一个部门表,dept_emp简况如下:

select *
from dept_emp;

  dept_emp表的详情如下:

  建表语句如下:

-- 首先创建employees表
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
-- 接着创建dept_emp表
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

  请你 查找所有已经分配部门的员工的last_name和first_name以及dept_no,未分配的部门的员工不显示,以上例子如下:

2、题目详解

  由于本题也是涉及到两张表查询,因此,我们应该可以用左连接来处理本题,具体用语句实现如下:

select last_name,first_name,dept_no
from employees left join dept_emp
on employees.emp_no = dept_emp.emp_no
where dept_emp.dept_no<>'';

  具体执行如下:

  这里需要我们在写查询语句的时候,特别注意判断部门编号为NULL的情况,这点需要我们特别注意。然后既然可以用左连接,我们也可以用自然连接,具体实现如下:

select e.last_name,e.first_name,d.dept_no
from employees e
join dept_emp d
on e.emp_no = d.emp_no

  具体执行的结果如下:

  当然我看到其它作者给出的一种答案也是极好的;按employees表中顺序输出的,所以使用内连接查询时,必须将employees表放在前面。具体实现如下:

select last_name,first_name,dept_no 
from employees,dept_emp 
where dept_emp.emp_no = employees.emp_no;

  具体执行结果如下:

五、查找所有已分配部门的员工的last_name和first_name以及对应的部门编号dept_no

1、题目描述

  本题与上题的表是一样的,因此,在这里不做说明,题目要求我们:请你 查找所有已经分配部门的员工的last_name和first_name以及dept_no,也包括暂时没有分配具体部门的员工,以上例子如下:

2、题目详解

  本题和上题还是一样的,需要我们多表连接,不过我们要注意的是:题目要求我们把dept_no为空值的显示出来,因此,不需要我们去除空值,具体实现如下:

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

  具体实现结果如下:

六、查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t

1、题目描述

  有一个薪水表,salaries简况如下:

select * 
from salaries;

  salaries详情如下:

  建表语句如下:

CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

  题目要求我们:请你 查找薪水记录超过15次的员工号emp_no以及其对应的记录次数t,以上例子输出如下:

2、题目详解

  本题要求我们查找薪水记录超过15次的员工号emp_no以及其对应的记录次数t,这就需要我们对员工的emp_no进行group by进行分组,然后用having进行筛选,具体实现如下:

select emp_no, count(emp_no) as t  
from salaries
group by emp_no
having t > 15;

  具体执行的结果如下:

七、找出所有员工当前具体的薪水情况

1、题目描述

  有一个薪水表,salaries简况如下:

select *
from salaries;

  salaries详情表如图所示:

  建表语句如下:

CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

  请你找出所有员工具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示,以上例子输出如下:

2、 题目详解

  这里有两种方法, 在查找中 使用不重复的应该用distinct,还有一种是通过分组和排序进行,具体实现如下:

select distinct salary 
from salaries
where to_date='9999-01-01'
order by salary desc

  执行结果如下:

  我们用group by实现如下:

select  salary 
from salaries
where to_date='9999-01-01'
group by salary
order by salary desc

  执行结果如下:

八、获取所有非manager的员工emp_no

1、题目描述

  有一个员工表employees简况如下:

select *
from employees;

  employees表详情如下:

  有一个部门领导表dept_manager简况如下:

select *
from dept_manager;

  dept_manage表详情如下:

  建表语句如下:

-- 首先建立`employees`表
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
-- 接着建立`dept_manager`表
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

  要求我们:请你 找出所有非部门领导的员工emp_no,以上例子输出:

2、题目解析

  本题要求我们查出所有非部门领导的员工emp_no,题目中又给了两张表,因此,我们很容易想到的就是多表连接查询,我们以employees表作为连接查询的主表。具体实现如下:

SELECT e.emp_no
FROM employees e LEFT JOIN dept_manager d
ON e.emp_no = d.emp_no 
WHERE dept_no IS NULL

  执行的结果如下:

  我们前面也介绍过,只要是能用多表连接查询的均可以按照嵌套使用,我们可以利用嵌套中的not in + 子查询来实现,具体实现如下:

SELECT emp_no 
FROM employees 
WHERE emp_no NOT IN(SELECT DISTINCT emp_no
                   FROM dept_manager);

  具体执行的结果如下:


  在嵌套中,我们可以用not exists + 子查询的方式进行查询,具体实现如下:

SELECT emp_no
FROM employees e
WHERE NOT EXISTS(SELECT DISTINCT d.emp_no 
                FROM dept_manager d
                WHERE e.emp_no = d.emp_no);

  具体执行的结果如下:

九、获取所有员工当前的manager

1、题目描述

  有一个员工表dept_emp简况如下:

select *
from dept_emp;

  dept_emp表详情如下:

  第一行表示为员工编号为10001的部门是d001部门。
  有一个部门经理表dept_manager简况如下:

select *
from dept_manager;

  dept_manager表详情如下:

  第一行表示为d001部门的经理是编号为10002的员工。
  这里要求我们 获取所有的员工和员工对应的经理,如果员工本身是经理的话则不显示,以上例子如下:

2、题目解析

  题目要求我们查找获取所有的员工和员工对应的经理,如果员工本身是经理的话则不显示。我们在做题之前首先要有以下的思路:

  • 首先确定需要输出的对象
       获取所有的员工和员工对应的经理,如果员工本身是经理的话则不显示。将员工表和经理表内部联结,联结条件是员工表的部门编号等于经理表的部门编号
  • 给表起别名,简化代码
  • 使用内部联结,inner join… on …
  • 筛选条件是员工本身是经理的不显示,即在联结表中只选择员工表中提取的员工编号与经理表中的经理编号不相同的行

  具体实现如下:

select e.emp_no,m.emp_no as manager
from dept_emp as e
inner join dept_manager as m
on e.dept_no = m.dept_no
where e.emp_no != m.emp_no
and e.to_date = '9999-01-01'
and m.to_date = '9999-01-01';

  具体执行如下:

十、获取所有部门中当前员工薪水最高的相关信息

1、 题目描述

  由于本题与上题的表是一致的,为了节省篇幅我们就不重复介绍了,本题要求我们 获取所有部门中员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary,按照部门编号升序排列,以上例子输出如下:

2、题目解析

  其实这道题目还是用到了两张表的连接,然后再用dept_no字段group by分组,具体实现如下:

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

  具体执行如下:

  接着我们可以用嵌套进行实现,具体实现如下:

SELECT d.dept_no,d.emp_no,s.salary
FROM 
dept_emp as d inner join salaries as s
on d.emp_no = s.emp_no and d.to_date = '9999-01-01' and s.to_date = '9999-01-01'
WHERE s.salary =
(
    SELECT MAX(s2.salary) as max_salary
    FROM dept_emp as d2 inner join salaries as s2
    ON d2.emp_no = s2.emp_no and d2.to_date = '9999-01-01' and s2.to_date = '9999-01-01' 
    where d2.dept_no = d.dept_no
    GROUP BY d2.dept_no
)
order by d.dept_no

  具体执行如下:

总结

  我们上篇文章给大家介绍了数据库查询语言中的单表查询理论的部分,主要包括全表查询、查询指定的列、去重、条件查询、模糊查询以及对查询的结果进行分组、排序以及限制。另外介绍了MySQL中常用的聚合函数和常用的一些运算符。在文章的最后我们介绍了MySQL查询语句在书写以及执行之间的区别。查询语言是MySQL中最为重要的一部分,需要我们在日常生活中多加练习。本文给大家介绍了牛客网中的前十道题作为我们本次表查询的练习。因此,mysql是很重要的一个技能,几乎计算机中的每个岗位都需要一个mysq技能,因此,需要我们特别的掌握。生命不息,奋斗不止,我们每天努力,好好学习,不断提高自己的能力,相信自己一定会学有所获。加油!!!

猜你喜欢

转载自blog.csdn.net/Oliverfly1/article/details/115022646