牛客SQL.26

135 阅读2分钟

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

描述

有一个部门表departments简况如下:

img

有一个,部门员工关系表dept_emp简况如下:

img

有一个职称表titles简况如下:

img

汇总各个部门当前员工的title类型的分配数目,即结果给出部门编号dept_no、dept_name、其部门下所有的员工的title以及该类型title对应的数目count,结果按照dept_no升序排序,dept_no一样的再按title升序排序

img

示例1

drop table if exists  `departments` ; 
drop table if exists  `dept_emp` ; 
drop table if exists  titles ;
CREATE TABLE `departments` (
`dept_no` char(4) NOT NULL,
`dept_name` varchar(40) NOT NULL,
PRIMARY KEY (`dept_no`));
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`));
CREATE TABLE titles (
`emp_no` int(11) NOT NULL,
`title` varchar(50) NOT NULL,
`from_date` date NOT NULL,
`to_date` date DEFAULT NULL);
INSERT INTO departments VALUES('d001','Marketing');
INSERT INTO departments VALUES('d002','Finance');
INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01');
INSERT INTO dept_emp VALUES(10002,'d001','1996-08-03','9999-01-01');
INSERT INTO dept_emp VALUES(10003,'d002','1995-12-03','9999-01-01');
INSERT INTO titles VALUES(10001,'Senior Engineer','1986-06-26','9999-01-01');
INSERT INTO titles VALUES(10002,'Staff','1996-08-03','9999-01-01');
INSERT INTO titles VALUES(10003,'Senior Engineer','1995-12-03','9999-01-01');
结果:
d001|Marketing|Senior Engineer|1
d001|Marketing|Staff|1
d002|Finance|Senior Engineer|1

方法一

先将题目要求的列都查询出来,放到一个结果集中;再将这个结果集作为表查询题目所要求的答案;

SELECT dept_no, dept_name, title, COUNT(*)
FROM
(
 SELECT A.*, B.title
 FROM
    (SELECT a.emp_no, a.dept_no, b.dept_name FROM dept_emp a, departments b WHERE a.dept_no=b.dept_no) A,
    titles B 
 WHERE A.emp_no=B.emp_no
) C
GROUP BY dept_no, title
ORDER BY dept_no, title

运行效果

按照惯例,我们打开optimizer_trace来看看具体发生了什么

image-20211109190720429

在准备阶段,mysql内部将语句优化成了如下:

SELECT a.dept_no, b.dept_name, B.title, COUNT(0) 
FROM dept_emp a, departments b, titles B
WHERE a.emp_no=B.emp_no AND a.dept_no=b.dept_no
GROUP BY a.dept_no, B.title
ORDER BY a.dept_no, B.title;

看起来确实比我自己写的简洁了许多;

由于三表连接,方式有许多种,这里只说明最后的连接顺序为b->B->ab驱动B驱动a;此种方法开销最低,开销为10.8;