分组查询是一个比较常见也稍微复杂一点的查询,比如查询每个班成绩最好的三名学生,每个部门工资最高的三个员工等等,今天就分享一下分组查询这样一个用法。
一、准备工作
首先上两张表,部门表和员工表。
部门表
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
INSERT INTO `department` VALUES ('1', '蜀');
INSERT INTO `department` VALUES ('2', '吴');
INSERT INTO `department` VALUES ('3', '魏');
员工表
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`salary` int(10) DEFAULT NULL,
`department_id` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4;
INSERT INTO `employee` VALUES ('1', '玄德', '20000', '1');
INSERT INTO `employee` VALUES ('2', '公瑾', '15000', '2');
INSERT INTO `employee` VALUES ('3', '云长', '22000', '1');
INSERT INTO `employee` VALUES ('4', '孟德', '15000', '3');
INSERT INTO `employee` VALUES ('5', '子龙', '17000', '1');
INSERT INTO `employee` VALUES ('6', '仲谋', '19000', '2');
INSERT INTO `employee` VALUES ('7', '奉孝', '17000', '3');
INSERT INTO `employee` VALUES ('8', '翼德', '18000', '1');
INSERT INTO `employee` VALUES ('9', '子敬', '12000', '2');
INSERT INTO `employee` VALUES ('10', '元让', '14000', '3');
现在我们的目标是查询出每个部门工资最高的三个员工(秉承着褒刘贬曹的态度,蜀国的工资当然是最高的),正确的查询结果如下:
感兴趣的同学可以先自己尝试一下,当然方法不止一种,这里博主提供其中一种方法:
SELECT
d.id AS d_id,
d.name AS d_name,
e1.id AS e_id,
e1.name AS e_name,
e1.salary AS e_salary
FROM
department AS d
LEFT JOIN employee AS e1 ON d.id = e1.department_id
WHERE
(
SELECT
COUNT(*)
FROM
employee AS e2
WHERE
e1.department_id = e2.department_id
AND e1.salary < e2.salary
) < 3
ORDER BY
d_id,
e_salary DESC
如果不太理解这个SQL的同学可以看一下下面的解析,理解的同学可以忽略。
解析:
我们把这条SQL分成三部分来解读,第一部分就是外层WHERE之前的部分
第一步
这一块应该很好理解,就是把部门表和员工表通过左外连接连接在一起,这一块代码的执行结果如下:
相当于就是把所有的部门和部门对应的员工信息查询出来,下一步我们需要从中选出各个部门工资最高的三个员工,所以我们需要加一些查询条件
第二步
第二步就是添加查询条件,这一步也是最重要的一步
这里可以这样理解,e1是刚才外层我们查询出来的表,e2就是单独的一张员工表,这里相当于把e1中的每一条数据与e2进行遍历比较(e1.department_id = e2.department_id AND e1.salary < e2.salary),说简单点,这个SELECT就是统计e2中工资比e1高的员工数量(相同部门),举个例子,比如COUNT(*)返回的是1,也就表示e2中只有一个员工比当前e1高,换句话说就是当前的e1是工资是当前部门第二高的,如果COUNT(*)返回的是2,就表示当前e1是工资第三高的,所以这里 < 3就表示选择选择工资前三的员工,但是这个时候还没有排序,所以下一步就是进行排序
第三步
第三步就是对查询出的数据进行排序
表达的不清楚的地方希望大家多多斟酌一下。