MySQL多表查询之横向连接

我们之前学习的SELECT语句都是单表查询,随着我们使用数据库的灵活性越来越高,当我们需要的数据在不同的表中时,就需要使用多表查询来检索我们需要的数据。
多表查询分为横向连接查询和纵向合并查询。
连接查询是通过多张表中共有的关键字段,将多张表连成一张虚拟结果集,来补充字段信息,我们可以按照业务需求检索多张表中的数据。

SQL查询的基本原理:

  • 单表查询:根据where条件过滤表中的记录,然后根据select指定的列返回查询结果。
  • 两表连接查询:使用on条件对两表进行连接形成一张虚拟结果集;然后根据where条件过滤结果集中的记录,再根据select指定的列返回查询结果。
  • 多表连接查询:先对第一个和第二个表按照两表连接查询,然后用用连接后的虚拟结果集和第三个表做连接查询,以此类推,直到所有的表都连接上为止,最终形成一张虚拟结果集,然后根据where条件过滤虚拟结果集中的记录,再根据select指定的列返回查询结果。

多表连接的结果通过三个属性决定:

  • 方向性:在外连接中写在前边的表为左表、写在后边的表为右表。
  • 主附关系:主表要出所有的数据范围,附表与主表无匹配项时标记为null,内连接时无主附表之分。
  • 对应关系:关键字段中有重复值的表为多表,没有重复值的表为一表。

对应关系:

  • 一对一
    在这里插入图片描述
  • 一对多或多对一
    在这里插入图片描述
  • 多对多
    在这里插入图片描述

MySQL支持的连接方式:内连接和外连接(左外连接、右外连接)。

  • 内连接:按照连接条件,返回两张表中满足条件的记录。
    在这里插入图片描述
select <字段名1>[,<字段名2>...,<字段名n>] from <表名1>[ inner] join <表名2> on <连接条件>

等值连接:连接条件是两张表中的关键字段取值相等。

mysql> select ename,job,hiredate,sal,dname
    -> from emp
    -> inner join dept
    -> on emp.deptno=dept.deptno;
+--------+-----------+------------+------+------------+
| ename  | job       | hiredate   | sal  | dname      |
+--------+-----------+------------+------+------------+
| clark  | manager   | 1981-06-09 | 2450 | accounting |
| king   | persident | 1981-11-17 | 5000 | accounting |
| miller | clerk     | 1982-01-23 | 1300 | accounting |
| smith  | clerk     | 1980-12-17 |  800 | research   |
| jones  | manager   | 1981-04-02 | 2975 | research   |
| scott  | analyst   | 1987-04-19 | 3000 | research   |
| adams  | clerk     | 1987-05-23 | 1100 | research   |
| ford   | analyst   | 1981-12-03 | 3000 | research   |
| allen  | salesman  | 1981-02-20 | 1600 | sales      |
| ward   | salesman  | 1981-02-22 | 1250 | sales      |
| martin | salesman  | 1981-09-28 | 1250 | sales      |
| blake  | manager   | 1981-05-01 | 2850 | sales      |
| turner | salesman  | 1981-09-08 | 1500 | sales      |
| james  | clerk     | 1981-12-03 |  950 | sales      |
+--------+-----------+------------+------+------------+

不等值连接:连接条件是两张表中的关键字段取值满足非等值比较运算。

mysql> select ename,job,hiredate,sal,grade
    -> from emp
    -> inner join salgrade
    -> on sal between losal and hisal;
+--------+-----------+------------+------+-------+
| ename  | job       | hiredate   | sal  | grade |
+--------+-----------+------------+------+-------+
| smith  | clerk     | 1980-12-17 |  800 |     1 |
| allen  | salesman  | 1981-02-20 | 1600 |     3 |
| ward   | salesman  | 1981-02-22 | 1250 |     2 |
| jones  | manager   | 1981-04-02 | 2975 |     4 |
| martin | salesman  | 1981-09-28 | 1250 |     2 |
| blake  | manager   | 1981-05-01 | 2850 |     4 |
| clark  | manager   | 1981-06-09 | 2450 |     4 |
| scott  | analyst   | 1987-04-19 | 3000 |     4 |
| king   | persident | 1981-11-17 | 5000 |     5 |
| turner | salesman  | 1981-09-08 | 1500 |     3 |
| adams  | clerk     | 1987-05-23 | 1100 |     1 |
| james  | clerk     | 1981-12-03 |  950 |     1 |
| ford   | analyst   | 1981-12-03 | 3000 |     4 |
| miller | clerk     | 1982-01-23 | 1300 |     2 |
+--------+-----------+------------+------+-------+

笛卡尔积连接:两张表中的每一条记录进行笛卡尔积组合,然后根据where条件过滤虚拟结果集中的记录。

select <字段名1>[,<字段名2>...,<字段名n>] from <表名1>,<表名2> where <筛选条件>
mysql> select ename,job,hiredate,sal,dname
    -> from emp,dept
    -> where emp.deptno=dept.deptno;
+--------+-----------+------------+------+------------+
| ename  | job       | hiredate   | sal  | dname      |
+--------+-----------+------------+------+------------+
| clark  | manager   | 1981-06-09 | 2450 | accounting |
| king   | persident | 1981-11-17 | 5000 | accounting |
| miller | clerk     | 1982-01-23 | 1300 | accounting |
| smith  | clerk     | 1980-12-17 |  800 | research   |
| jones  | manager   | 1981-04-02 | 2975 | research   |
| scott  | analyst   | 1987-04-19 | 3000 | research   |
| adams  | clerk     | 1987-05-23 | 1100 | research   |
| ford   | analyst   | 1981-12-03 | 3000 | research   |
| allen  | salesman  | 1981-02-20 | 1600 | sales      |
| ward   | salesman  | 1981-02-22 | 1250 | sales      |
| martin | salesman  | 1981-09-28 | 1250 | sales      |
| blake  | manager   | 1981-05-01 | 2850 | sales      |
| turner | salesman  | 1981-09-08 | 1500 | sales      |
| james  | clerk     | 1981-12-03 |  950 | sales      |
+--------+-----------+------------+------+------------+

自连接:通过设置表别名,将一张表虚拟成多张表。

mysql> select t1.ename as 员工姓名,t2.ename as 领导姓名
    -> from emp as t1
    -> inner join emp as t2
    -> on t1.mgr=t2.empid;
+----------+----------+
| 员工姓名 | 领导姓名 |
+----------+----------+
| smith    | ford     |
| allen    | blake    |
| ward     | blake    |
| jones    | king     |
| martin   | blake    |
| blake    | king     |
| clark    | king     |
| scott    | jones    |
| turner   | blake    |
| adams    | scott    |
| james    | blake    |
| ford     | jones    |
| miller   | clark    |
+----------+----------+

表限定符.:如果表1和表2中的字段名相同,则必须使用表限定符.指定引用的是哪个表中的字段。

  • 左连接:按照连接条件,返回两张表中满足条件的记录,以及左表中的所有记录,右表匹配不到显示为null。
    在这里插入图片描述
select <字段名1>[,<字段名2>...,<字段名n>] from <表名1> left join <表名2> on <连接条件>

示例:查询每个部门的员工数(没有员工的部门,员工数统计为0)

mysql> select dept.deptno,dname,count(empid)
    -> from dept
    -> left join emp
    -> on dept.deptno=emp.deptno
    -> group by dept.deptno;
+--------+------------+--------------+
| deptno | dname      | count(empid) |
+--------+------------+--------------+
|     10 | accounting |            3 |
|     20 | research   |            5 |
|     30 | sales      |            6 |
|     40 | operations |            0 |
+--------+------------+--------------+
  • 右连接:按照连接条件,返回两张表中满足条件的记录,以及右表中的所有记录,左表匹配不到显示为null。
    在这里插入图片描述
select <字段名1>[,<字段名2>...,<字段名n>] from <表名1> right join <表名2> on <连接条件>

示例:查询每个部门的员工数(没有员工的部门,员工数统计为0)

mysql> select dept.deptno,dname,count(empid)
    -> from emp
    -> right join dept
    -> on dept.deptno=emp.deptno
    -> group by dept.deptno;
+--------+------------+--------------+
| deptno | dname      | count(empid) |
+--------+------------+--------------+
|     10 | accounting |            3 |
|     20 | research   |            5 |
|     30 | sales      |            6 |
|     40 | operations |            0 |
+--------+------------+--------------+

多表连接规则

  • 确定查询的信息在哪几张表
  • 确定表和表之间的对应关系和主附关系
  • 确定表和表之间的连接条件

一表作为主表可以保证维度的完整性,多表作为主表可以保证度量的准确性。在没有明确表示需要保证维度完整性的情况下,优先保证度量的准确性,所以将度量值所在的表作为主表。度量字段通常存在于多表中,因此通常情况下可以将多表作为主表进行外连接。

猜你喜欢

转载自blog.csdn.net/kejiayuan0806/article/details/105652902
今日推荐