【MySQL学习笔记】系列七:MySQL的多表查询(一)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 【MySQL学习笔记】系列七:MySQL的多表查询(一)

一、 一个案例引发的多表连接


1.1 案例说明

5f692b0e3ed8b600de6541523c8020ff_65f965b4978c1c44fdfd4f0c40814896.png


从多个表中获取数据:


c6c878bbe597e45bb23a3650691bfc07_42aab9a580145a6e1cfb05d0521432b2.png


#案例:查询员工的姓名及其部门名称
SELECT last_name, department_name
FROM employees, departments;


fe0c84971320841fe15f7ef115dad982_f48f1aca4bf7b4388881a0b95195349d.png


查询结果:


+-----------+----------------------+
| last_name | department_name      |
+-----------+----------------------+
| King      | Administration       |
| King      | Marketing            |
| King      | Purchasing           |
| King      | Human Resources      |
| King      | Shipping             |
| King      | IT                   |
| King      | Public Relations     |
| King      | Sales                |
| King      | Executive            |
| King      | Finance              |
| King      | Accounting           |
| King      | Treasury             |
...
| Gietz     | IT Support           |
| Gietz     | NOC                  |
| Gietz     | IT Helpdesk          |
| Gietz     | Government Sales     |
| Gietz     | Retail Sales         |
| Gietz     | Recruiting           |
| Gietz     | Payroll              |
+-----------+----------------------+
2889 rows in set (0.01 sec)


分析错误情况:


SELECT COUNT(employee_id) FROM employees;
#输出107行
SELECT COUNT(department_id)FROM departments;
#输出27行
SELECT 107*27 FROM dual;


我们把上述多表查询中出现的问题称为:笛卡尔积的错误。


1.2 笛卡尔积(或交叉连接)的理解


笛卡尔乘积是一个数学运算。假设我有两个集合 X 和 Y,那么 X 和 Y 的笛卡尔积就是 X 和 Y 的所有可能组合,也就是第一个对象来自于 X,第二个对象来自于 Y 的所有可能。组合的个数即为两个集合中元素个数的乘积数。


e9367cfa8c56ca770ae4a6be909f7089_302046364841977.jpg


SQL92中,笛卡尔积也称为交叉连接,英文是 CROSS JOIN。在 SQL99 中也是使用 CROSS JOIN表示交叉连接。它的作用就是可以把任意表进行连接,即使这两张表不相关。在MySQL中如下情况会出现笛卡尔积:


#查询员工姓名和所在部门名称
SELECT last_name,department_name FROM employees,departments;
SELECT last_name,department_name FROM employees CROSS JOIN departments;
SELECT last_name,department_name FROM employees INNER JOIN departments;
SELECT last_name,department_name FROM employees JOIN departments;


1.3 案例分析与问题解决


笛卡尔积的错误会在下面条件下产生:


省略多个表的连接条件(或关联条件)

连接条件(或关联条件)无效

所有表中的所有行互相连接

为了避免笛卡尔积, 可以在 WHERE 加入有效的连接条件。


加入连接条件后,查询语法:


SELECT  table1.column, table2.column
FROM  table1, table2
WHERE table1.column1 = table2.column2;  #连接条件


在 WHERE子句中写入连接条件。

正确写法:


#案例:查询员工的姓名及其部门名称
SELECT last_name, department_name
FROM employees, departments
WHERE employees.department_id = departments.department_id;



在表中有相同列时,在列名之前加上表名前缀。


二、 多表查询分类讲解


分类1:等值连接 vs 非等值连接

等值连接


0c18ce558718ff65e05ca98fcfe509f0_0ecf01fef9163e79769c38bb611f8659.png


SELECT employees.employee_id, employees.last_name, 
       employees.department_id, departments.department_id,
       departments.location_id
FROM   employees, departments
WHERE  employees.department_id = departments.department_id;


64a329535bb580dcdc3c9e7c887288f9_9e7f35c8616322efd9d38b376e3b617e.png


拓展1:多个连接条件与 AND 操作符


a4f5a56a16f949c7775ab0cc17691530_aa72c5b6082a11ddd3502063ae1cf69d.png


拓展2:区分重复的列名


多个表中有相同列时,必须在列名之前加上表名前缀。
在不同表中具有相同列名的列可以用表名加以区分。
SELECT employees.last_name, departments.department_name,employees.department_id
FROM employees, departments
WHERE employees.department_id = departments.department_id;


拓展3:表的别名


使用别名可以简化查询。


列名前使用表名前缀可以提高查询效率。


SELECT e.employee_id, e.last_name, e.department_id,
       d.department_id, d.location_id
FROM   employees e , departments d
WHERE  e.department_id = d.department_id;


需要注意的是,如果我们使用了表的别名,在查询字段中、过滤条件中就只能使用别名进行代替,不能使用原有的表名,否则就会报错。


阿里开发规范:


【强制】对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名(或 表名)进行限定。


说明:对多表进行查询记录、更新记录、删除记录时,如果对操作列没有限定表的别名(或表名),并且操作列在多个表中存在时,就会抛异常。


正例:select t1.name from table_first as t1 , table_second as t2 where t1.id=t2.id;


反例:在某业务中,由于多表关联查询语句没有加表的别名(或表名)的限制,正常运行两年后,最近在 某个表中增加一个同名字段,在预发布环境做数据库变更后,线上查询语句出现出 1052 异常:Column ‘name’ in field list is ambiguous。


拓展4:连接多个表


7ca279d021018aff11a60d851e6a2d04_aa2af07cbd3e61c7a47be256d1b31762.png


**总结:连接 n个表,至少需要n-1个连接条件。**比如,连接三个表,至少需要两个连接条件。


练习:查询出公司员工的 last_name,department_name, city


非等值连接


a19d504bb09ccc63a4d622144df246a9_a792e9039a316867c74e8a2b6868dcda.png


SELECT e.last_name, e.salary, j.grade_level
FROM   employees e, job_grades j
WHERE  e.salary BETWEEN j.lowest_sal AND j.highest_sal;


a5676163059a392958487e67f9ac4023_e62db857d70cba9b6ec216c9053f2747.png


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VxW0IM7Y-1652627536920)(images/1554978482652.png)]


分类2:自连接 vs 非自连接


75f17cdcabf7901cee48d36910b339b1_49ac8c3f6c5a2879774dd6666739cdce.png


当table1和table2本质上是同一张表,只是用取别名的方式虚拟成两张表以代表不同的意义。然后两个表再进行内连接,外连接等查询。

题目:查询employees表,返回“Xxx works for Xxx”


SELECT CONCAT(worker.last_name ,' works for ' 
       , manager.last_name)
FROM   employees worker, employees manager
WHERE  worker.manager_id = manager.employee_id ;


dda148c1cc8380f0b216e4ed0dcbada8_60fd2d148e0d238fbbfe7eefec629384.png


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OuuncnGc-1652627536924)(images/1554978690764.png)]


练习:查询出last_name为 ‘Chen’ 的员工的 manager 的信息。


分类3:内连接 vs 外连接

除了查询满足条件的记录以外,外连接还可以查询某一方不满足条件的记录。


760a360f42f5673d014e3055c3a1cba1_13d0dad50dfedcec0ade61664de5ddde.png


内连接: 合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行


外连接: 两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行 ,这种连接称为左(或右) 外连接。没有匹配的行时, 结果表中相应的列为空(NULL)。


如果是左外连接,则连接条件中左边的表也称为主表,右边的表称为从表。


如果是右外连接,则连接条件中右边的表也称为主表,左边的表称为从表。


SQL92:使用(+)创建连接

在 SQL92 中采用(+)代表从表所在的位置。即左或右外连接中,(+) 表示哪个是从表。


Oracle 对 SQL92 支持较好,而 MySQL 则不支持 SQL92 的外连接。


#左外连接
SELECT last_name,department_name
FROM employees ,departments
WHERE employees.department_id = departments.department_id(+);
#右外连接
SELECT last_name,department_name
FROM employees ,departments
WHERE employees.department_id(+) = departments.department_id;


而且在 SQL92 中,只有左外连接和右外连接,没有满(或全)外连接。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
9天前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
43 6
|
9天前
|
SQL 关系型数据库 MySQL
Mysql学习笔记(三):fetchone(), fetchmany(), fetchall()详细总结
MySQL中用于数据检索的`fetchone()`, `fetchmany()`, `fetchall()`函数的功能、SQL语句示例和应用场景。
25 3
Mysql学习笔记(三):fetchone(), fetchmany(), fetchall()详细总结
|
9天前
|
SQL Ubuntu 关系型数据库
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
本文为MySQL学习笔记,介绍了数据库的基本概念,包括行、列、主键等,并解释了C/S和B/S架构以及SQL语言的分类。接着,指导如何在Windows和Ubuntu系统上安装MySQL,并提供了启动、停止和重启服务的命令。文章还涵盖了Navicat的使用,包括安装、登录和新建表格等步骤。最后,介绍了MySQL中的数据类型和字段约束,如主键、外键、非空和唯一等。
30 3
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
|
9天前
|
关系型数据库 MySQL 数据库
Mysql学习笔记(四):Python与Mysql交互--实现增删改查
如何使用Python与MySQL数据库进行交互,实现增删改查等基本操作的教程。
20 1
|
4月前
|
SQL Oracle 关系型数据库
MySQL学习笔记
MySQL学习笔记
33 0
|
2月前
|
SQL druid Java
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下)
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)
52 3
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下)
|
2月前
|
SQL Java 关系型数据库
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(上)
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)
92 3
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(上)
|
2月前
|
SQL 关系型数据库 MySQL
MySQL学习笔记
这篇文章是一份关于MySQL数据库操作的学习笔记,涵盖了数据库的终端操作、数据类型、建表约束、事务处理以及SQL的连接查询等基础知识点。
|
2月前
|
SQL 关系型数据库 MySQL
Java数据库部分(MySQL+JDBC)(一、MySQL超详细学习笔记)(下)
Java数据库部分(MySQL+JDBC)(一、MySQL超详细学习笔记)
34 6
|
2月前
|
存储 关系型数据库 MySQL
Java数据库部分(MySQL+JDBC)(一、MySQL超详细学习笔记)(上)
Java数据库部分(MySQL+JDBC)(一、MySQL超详细学习笔记)
40 4