MySQL外连接
不渴望力量的哈士奇 人气:0该章节的内容为多表连接查询的外连接,因为 MySQL 是关系型数据库,数据是拆分重组在多个数据表里面的。所以我们势必要从多个数据表中提取数据,通过 SQL 语句的内连接与外连接就能够实现多表查询了。这部分内容是需要我们重点学习的,学习的过程中会穿插多种的案例来强化对表连接的语法的运用。
为什么要使用外连接
在解释为什么使用 “外连接” 之前,先来看一个记录。(如下:)
针对表中的张三没有所属的部门编号,我们暂且将他归类为 “临时工” ,没有固定的部门编制。
介于如此的场景,那么问题就出现了。当我们想要查询每一名员工和他的所属部门的名称时,在使用内连接的情况下,因为我们的链接条件是` “员工表” 的 “部门编号” = “部门表” 的 “部门编号” ,就会将 “张三” 漏掉。虽然说 “张三” 没有 “部门编号” ,但是他作为 “临时工” 也是公司的一员, 所以要引入外连接的语法才能解决这个问题,否则就会丢失一些符合逻辑的数据。
外连接简介
外连接与内连接的区别:
内连接的结果接中只会出现符合连接条件的记录,不符合连接条件的记录是绝对不会出现在结果集里面的。
外连接则显得很特殊,无论是否符合数据连接条件,都会出现在结果级里。(就比如上文提到的查询员工部门标号信息,因为 “张三” 没有部门编号,如果使用内连接,则 “张三” 就不符合 “连接条件”,也就不会出现在结果集里面;换做 “外连接” 就不会漏掉了。 )
外连接 例句 如下
SELECT e.empno, e.ename, d.dname FROM t_emp e LEFT JOIN t_dept d ON e.deptno = d.deptno; -- 在连接的时候仍然是链接 "员工表" 与 "部门表" ,只不过连接关键字由 "JOIN" 变成了 "LEFT JOIN" (下文再为大家详细解释) -- 两张表的连接条件还是使用 "ON" 关键字去连接的 , 连接条件依然是 "员工表" 的 "部门编号" = "部门表" 的 "部门编号" -- LEFT JOIN 为 "外连接" 的 "左外连接" ;(在 "外连接" 中,是分为 "左外连接" 与 "右外连接" 的) -- 在该SQL语句中 "LEFT JOIN" 左右各有数据表 "t_emp e" 与 "t_dept d" -- 所以这里的 "左连接" 的意思就是:保留 左表 的所有记录,然后与 右表 去连接,如果 右表 有符合条件的记录,则正常连接即可; -- 如果 右表 没有符合条件的连接记录, 右表 则展示 "NULL" 值与 "左表" 去匹配
左连接与右连接
“左连接” 也被称之为 “左外连接” ,就是保留左表所有的记录,与右表做连接。如果右表有符合条件的记录就与左表连接;如果右表没有符合条件的记录,就用 “NULL” 与左表连接。
区别于 “左连接” 的就是 “右连接”,“右连接” 与 “左连接” 相反,是保留 右表 的所有记录与 左表 的符合条件的记录进行连接;同样的,如果左表没有符合条件的记录,就用 “NULL” 与右表连接。
右连接 SQL 语句示例:
SELECT e.empno, e.ename, d.dname FROM t_dept d RIGHT JOIN t_emp e ON e.deptno = d.deptno; -- 这里有个需要注意的地方,就是相较于上文中的 "左连接" ,这里的 "右连接" 左右两张的表的位置做了调换
在这里,大家可以看到,仍然可以查出来 “张三” 的没有 “部门编号” 的记录。所以说 “左连接” 与 “右连接” 的区别并不是很大。
外连接练习①
查询每个部门的名称和部门的人数?
这道题看似简单,但是里面存在着两个难点,而且也存在容易出错的地方,详见下文 SQL 语句示例,与示意图。
SELECT d.deptno, d.dname, COUNT(*) FROM t_dept d LEFT JOIN t_emp e ON d.deptno = e.deptno GROUP BY d.deptno;
OK,问题就在这里开始出现了。
大家注意这里的 “40” - “OPERATIONS” 部门,这个部门实际上是没有人的,也就是人数为 “0” ,但是奇怪的是,这里进行统计的时候,却出现了统计人数 “1” ,这是为什么呢?
这是因为我们在使用分组的时候,用的是 “左连接” ,保留了左表的所有的数据,所以就按照左表的 “deptno” 进行分组。(因为是保留了左表的记录,所以分组也需要按照左表进行分组。);接下来重要的就是 “COUNT(*)” 这一部分了,“COUNT(*)” 统计的是所有的有效记录。所以当左表 “t_dept” 的所有记录与 右表 “t_emp” 进行连接的时候,右表 会使用 "NULL"值 与 左表 “t_dept” 连接,连接完之后就是一条有效的记录,如此既然是有效记录,那么 “COUNT(*)” 统计到的结果就是 “1”。
所以,如此统计到 40 部门的统计结果 为 “1” ,也是情有可原的,但是这个结果并不是我们想要的,要怎么去解决呢?参考下方的 SQL 语句。
SELECT d.deptno, d.dname, COUNT(e.deptno) FROM t_dept d LEFT JOIN t_emp e ON d.deptno = e.deptno GROUP BY d.deptno;
这个 SQL 语句还是非常不错的,有非常多的细节与未考虑到的情况,只有真正写一遍的时候才能会注意到这些袭击。
外连接练习②
查询每个部门的名称和部门的人数?如果是没有部门的员工,部门名称用 “NULL” 替代。(这里其实就是指的 "张三")
可能这里会觉得刚刚使用的是 "左外连接" 保留的部门表中所有的记录,这里直接换成 "右" 外连接不就行了么?其实...没那么简单。
这个练习的 SQL 语句需要使用到"UNION"关键字 去实现,利用"UNION" 关键字将多个查询语句的结果集进行并集的合并处理(排除重复内容)。
"UNION"关键字 在 SQL 语句中的用法如下:
(SQL查询语句) UNION (SQL查询语句) -- 如果存在多条查询语句的话,可以继续使用 UNION 关键字 连接
PS:这里需要注意一下,“UNION” 合并多少个结果集其实无所谓,关键是这些结果集的字段数量和字段的名称必须要相同 。如果说第一个 SQL 查询语句返回的是 10个 字段,第二个返回的是 2个字段 ,这种情况是完全没办法合并的。
(SELECT d.deptno, d.dname, COUNT(e.deptno) FROM t_dept d LEFT JOIN t_emp e ON d.deptno = e.deptno GROUP BY d.deptno) UNION (SELECT d.deptno, d.dname, COUNT(*) FROM t_dept d RIGHT JOIN t_emp e ON d.deptno = e.deptno GROUP BY d.deptno); -- 第一个查询语句,得到的结果集是各个部门的人数。 -- 第二个查询语句,得到的结果集是隶属于各个部门的人数,但是因为 "张三" 是一个没有部门所属的 "临时工" -- 所以两个查询语句的结果集合并之下没救如下图所示。
加载全部内容