数据库类型:MySQL新理解

在SQL脚本中如果存在内外(或父子)关联条件的子查询时,可以将子查询理解为“使用父查询的一条数据中的字段值作为条件,过滤子查询的结果“。

举例

SELECT d.`name` Department, e1.`name` Employee, e1.salary salary FROM Employee e1,Department d where e1.departmentId = d.id and (select count(DISTINCT e2.salary) from Employee e2 where e1.salary <= e2.salary AND e1.departmentId = e2.departmentId) <= 3 order by 1,3 desc

子查询“select count(DISTINCT e2.salary) from Employee e2 where e1.salary <= e2.salary AND e1.departmentId = e2.departmentId”中含有父查询的条件字段“e1.departmentId”和“e1.salary”。

详解

今天在逛LeetCode的时候,看到了一道数据库的题目,编写一个 SQL 查询,找出每个部门获得前三高工资的所有员工。

尝试写了一下,但写的特复杂,就不丢人现眼了。去看评论的时候,看到了牛人的写法,照着照着他的思路思考了一下,最终写出了举例中的SQL,执行过后正确无误。

一开始对其中的子查询不是和理解,为什么要这么写?为什么在子查询中使用count进行统计?最终子查询外的“<=3"又是个什么操作?

仔细想想,子查询中有父查询的条件字段“e1.departmentId”和“e1.salary”,这两个字段就将子查询的数据过滤了出来。

针对外(父)查询的一条数据在使用子查询进行匹配的时候,子查询的数据就被这两个条件过滤掉了。

对于示例SQL讲解

使用外(父)查询的数据作为子查询的条件,及匹配与父查询的数据是同一个部门(department)的且薪资(salary)高于父查询的数据,这样的数据根据薪资金额去重后计数,如果少于等于3个,则说明父查询的这条数据中记录的员工的薪资在本部门内是排在前三位的。

吐槽

我要吐槽一下LeetCode的测试用例,下图这种的测试用例就等于小学考试中出题“小明今天很高兴,问小花的心里阴影面积是多少?”。竟然会使用这种有部门ID在员工表中记录,但是部门表中没有记录的情况,而且在这种情况下还必须要catch住这种异常情况。

sql关联查询的结果(对SQL中存在内外或父子)(1)

如果真发生了这种情况(部门信息被删除了但是员工表中还记录这部门信息),只有一个原因:系统出现了BUG,在删部门信息的时候没有做校验。

退一步讲:一个员工从一个部分转到了另一个部门,原先的部门被取消了,但是人力系统中没有及时维护新员工的部门,但该员工在新的部门工作很出众,那么统计优秀员工的时候,该名员工就要被排除在外么?

附上建表及数据脚本

CREATE TABLE `Department` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ); BEGIN; INSERT INTO `Department` VALUES (1, 'IT'); INSERT INTO `Department` VALUES (2, 'Sales'); COMMIT; CREATE TABLE `Employee` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `salary` bigint(20) DEFAULT NULL, `departmentId` int(10) DEFAULT NULL, PRIMARY KEY (`id`) ); BEGIN; INSERT INTO `Employee` VALUES (1, 'Joe', 85000, 1); INSERT INTO `Employee` VALUES (2, 'Henry', 80000, 2); INSERT INTO `Employee` VALUES (3, 'Sam', 60000, 2); INSERT INTO `Employee` VALUES (4, 'Max', 90000, 1); INSERT INTO `Employee` VALUES (5, 'Janet', 69000, 1); INSERT INTO `Employee` VALUES (6, 'Randy', 85000, 1); INSERT INTO `Employee` VALUES (7, 'Will', 70000, 1); COMMIT;

作者:BTMonkey

原文:https://my.oschina.net/cuttese/blog/4888438

,