牛客SQL.1

238 阅读4分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

描述

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

img

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

示例1

drop table if exists  `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`));
INSERT INTO employees VALUES(10001,'1953-09-02','Georgi','Facello','M','1986-06-26');
INSERT INTO employees VALUES(10002,'1964-06-02','Bezalel','Simmel','F','1985-11-21');
INSERT INTO employees VALUES(10003,'1959-12-03','Parto','Bamford','M','1986-08-28');
INSERT INTO employees VALUES(10004,'1954-05-01','Chirstian','Koblick','M','1986-12-01');
INSERT INTO employees VALUES(10005,'1955-01-21','Kyoichi','Maliniak','M','1989-09-12');
INSERT INTO employees VALUES(10006,'1953-04-20','Anneke','Preusig','F','1989-06-02');
INSERT INTO employees VALUES(10007,'1957-05-23','Tzvetan','Zielinski','F','1989-02-10');
INSERT INTO employees VALUES(10008,'1958-02-19','Saniya','Kalloufi','M','1994-09-15');
INSERT INTO employees VALUES(10009,'1952-04-19','Sumant','Peac','F','1985-02-18');
INSERT INTO employees VALUES(10010,'1963-06-01','Duangkaew','Piveteau','F','1989-08-24');
INSERT INTO employees VALUES(10011,'1953-11-07','Mary','Sluis','F','1990-01-22');
​
输出:10008|1958-02-19|Saniya|Kalloufi|M|1994-09-15

方法一

根据雇佣日期降序排序,选择第一个就是为最晚入职的员工

select * from employees order by hire_date desc limit 1

然而,雇佣日期具体到天,所以可能存在在同一天内多个人入职的情况。这么看来方法一并不严谨,我们来稍微改造一下方法一得到方法二。

方法二

方法一已经得到了最晚入职的员工,问题在于可能还存在其他员工在那一天中入职。所以我们利用方法一查询得到的最晚入职日期,作为条件再去查表;

select employees.* 
from employees, (select * from employees order by hire_date desc limit 1) as res 
where employees.hire_date=res.hire_date

还有另一种实现方式,将条件放在where中

select * from employees
where employees.hire_date=(select hire_date from employees order by hire_date desc limit 1)

运行效果

虽然第一种方法不严谨但也能通过,所以本题看,方法一优于方法二;而方法二中,我们用explain命令来看看,具体是如何执行的:

  • 对于第一种实现方式:

    • image-20211102194650408

      每个select语句都有一个id,从表中也可以看出id值有1,2;

      对于id为1的select查询,它的select_type为primary,表示一条sql语句中包含子查询时,最左边select的类型为primary;

      table列的意思为,查询的表为employees和,employees很好理解,就是本表;而是什么呢?它表示查询的是一个物化表;从id为2的select语句中的select_type也可以看出,from后面的子查询返回的结果集(称为派生表),采用物化的方式来查询;(物化就是在根据结果集的大小来创建一张临时表,集合比较小时,可以存在内存中,使用memory存储引擎,而且会为该表建立哈希索引;集合较大时,使用基于磁盘的存储引擎,索引使用B+树索引);

      type列表示的对该表进行查询时的访问方式:ALL代表全表扫描,system代表当表中只有一条记录并且该表使用的存储引擎的统计数据是精确的,比如MyISAM、Memory,那么对该表的访问方法就是system;

      row列:预计需要扫描的行数

      filtered列:代表在预计扫描的行中,该条select语句过滤完还能剩下多少的比例;

      extra列:记录一些额外信息,比如select_id=1的查询中,使用了where条件,select_id=2的查询中,使用了文件排序;

  • 对于第二种实现方式:

    • image-20211102201205120

      经过上面的解释,大致都能明白,其中select_id=2的查询类型为子查询;