MySQL基础教程15——多表查询

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 笛卡尔积显示出来的数据会有我们不需要的,因此我们可以用条件筛选掉不需要的条件。

MySQL基础教程15——多表查询


MySQL基础教程15——多表查询


笛卡尔积

mysql> select * from user;
+----+------+--------+---------+
| id | name | gender | user_id |
+----+------+--------+---------+
|  1 | ton  | 男     |       1 |
|  2 | bom  | 女     |       2 |
|  3 | lin  | 男     |       3 |
+----+------+--------+---
mysql> select * from foot;
+----+------+
| id | s    |
+----+------+
|  1 | 苹果 |
|  2 | 香蕉 |
|  3 | 橘子 |
+----+------+
3 rows in set (0.03 sec)
// 笛卡尔积
mysql> select * from user,foot;
+----+------+--------+---------+----+------+
| id | name | gender | foot_id | id | s    |
+----+------+--------+---------+----+------+
|  1 | ton  | 男     |       1 |  1 | 苹果 |
|  2 | bom  | 女     |       2 |  1 | 苹果 |
|  3 | lin  | 男     |       3 |  1 | 苹果 |
|  1 | ton  | 男     |       1 |  2 | 香蕉 |
|  2 | bom  | 女     |       2 |  2 | 香蕉 |
|  3 | lin  | 男     |       3 |  2 | 香蕉 |
|  1 | ton  | 男     |       1 |  3 | 橘子 |
|  2 | bom  | 女     |       2 |  3 | 橘子 |
|  3 | lin  | 男     |       3 |  3 | 橘子 |
+----+------+--------+---------+----+------+
9 rows in set (0.03 sec)

以这两张表为例子笛卡尔积现象就是表A的每一个记录与表B的每一个记录匹配组成一条新纪录,例如表A有三条记录表B有三条记录结合后就为3*3(9)条记录。


内连接


笛卡尔积显示出来的数据会有我们不需要的,因此我们可以用条件筛选掉不需要的条件。


隐式内连接


select 字段列表 from 表1,表2 where 条件;

mysql> select * from user as u,foot as f where u.foot_id = f.id;
+----+------+--------+---------+----+------+
| id | name | gender | foot_id | id | s    |
+----+------+--------+---------+----+------+
|  1 | ton  | 男     |       1 |  1 | 苹果 |
|  2 | bom  | 女     |       2 |  2 | 香蕉 |
|  3 | lin  | 男     |       3 |  3 | 橘子 |
+----+------+--------+---------+----+------+
3 rows in set (0.03 sec)

显式内连接


select 字段列表 from 表1 [inner] join 表2 on 连接条件;

mysql> select * from user as u inner join foot as f on u.foot_id = f.id;
+----+------+--------+---------+----+------+
| id | name | gender | foot_id | id | s    |
+----+------+--------+---------+----+------+
|  1 | ton  | 男     |       1 |  1 | 苹果 |
|  2 | bom  | 女     |       2 |  2 | 香蕉 |
|  3 | lin  | 男     |       3 |  3 | 橘子 |
+----+------+--------+---------+----+------+
3 rows in set (0.03 sec)

相对而言,隐式连接好理解好书写,语法简单,担心的点较少。但是显式连接可以减少字段的扫描,有更快的执行速度。这种速度优势在3张或更多表连接时比较明显。


外连接


往user中添加一条新记录,字段foot_id为null。

mysql> select * from user;
+----+------+--------+---------+
| id | name | gender | foot_id |
+----+------+--------+---------+
|  1 | ton  | 男     |       1 |
|  2 | bom  | 女     |       2 |
|  3 | lin  | 男     |       3 |
|  4 | ken  | 女     | NULL    |
+----+------+--------+---------+
4 rows in set (0.04 sec)
mysql> select * from user,foot where user.foot_id = foot.id;
+----+------+--------+---------+----+------+
| id | name | gender | foot_id | id | s    |
+----+------+--------+---------+----+------+
|  1 | ton  | 男     |       1 |  1 | 苹果 |
|  2 | bom  | 女     |       2 |  2 | 香蕉 |
|  3 | lin  | 男     |       3 |  3 | 橘子 |
+----+------+--------+---------+----+------+
3 rows in set (0.04 sec)

此时用内连接会发现条件字段为空的就查询不出来,因此我们可以用外连接连解决。


左外连接(左表全部和左右表交集)


select 字段列表 from 表1 left [outer] join 表2 on 条件;

mysql> select u.*,f.* from user as u left outer join foot as f on u.foot_id = f.id;
+----+------+--------+---------+------+------+
| id | name | gender | foot_id | id   | s    |
+----+------+--------+---------+------+------+
|  1 | ton  | 男     |       1 |    1 | 苹果 |
|  2 | bom  | 女     |       2 |    2 | 香蕉 |
|  3 | lin  | 男     |       3 |    3 | 橘子 |
|  4 | ken  | 女     | NULL    | NULL | NULL |
+----+------+--------+---------+------+------+
4 rows in set (0.03 sec)

右边外连接(右表全部和左右表交集)


select 字段列表 from 表1 right [outer] join 表2 on 条件;

mysql> select f.*,u.* from user as u right outer join foot as f on u.foot_id = f.id;
+----+------+----+------+--------+---------+
| id | s    | id | name | gender | foot_id |
+----+------+----+------+--------+---------+
|  1 | 苹果 |  1 | ton  | 男     |       1 |
|  2 | 香蕉 |  2 | bom  | 女     |       2 |
|  3 | 橘子 |  3 | lin  | 男     |       3 |
+----+------+----+------+--------+---------+
3 rows in set (0.03 sec)

这里没有显示user表中id为4的信息是因为在foot表中字段id没有对应user表中字段foot_id的null值。


本质上来说左外连接和右外连接是一样的只要把表的位置换一下实现的效果就能一样,例如:

//左外连接
select * from user as u left outer join foot as f on u.foot_id = f.id; 
//右外连接
select * from foot as f right outer join user as u on u.foot_id = f.id; 

这两句SQL语句执行的效果是一致的。


自连接


自连接可以和内外连接一起使用。

mysql> select * from yg;
+----+------+------+
| id | name | t_id |
+----+------+------+
|  1 | 张三 | NULL |
|  2 | 李四 |    1 |
|  3 | 王五 |    1 |
|  4 | 熊大 |    2 |
+----+------+------+
4 rows in set (0.05 sec)

t_id字段对应的id表示上级关系,现在需要查询每个人对应的上级就需要用到自连接。

mysql> select a.name,b.name from yg as a left outer join yg as b on a.t_id = b.id;
+------+------+
| name | name |
+------+------+
| 李四 | 张三 |
| 王五 | 张三 |
| 熊大 | 李四 |
| 张三 | NULL |
+------+------+
4 rows in set (0.03 sec)

自连接本质上就是一张表取两个不同的别名当两张表使用。


联合查询


当我们对多表进行查询时,想把数据汇集在一张表上可以使用联合查询。


select 字段列表 from 表1 .... union[all] select 字段列表 from 表2 ...;

假设我们需要查询user表中id为2的人的信息和yg表中id为3的人的信息并且汇总在一张表上。

mysql> select u.id,u.name,u.gender from user as u where id = 2
    -> union all 
    -> select * from yg where id = 3;
+----+------+--------+
| id | name | gender |
+----+------+--------+
|  2 | bom  | 女     |
|  3 | 王五 | 1      |
+----+------+--------+
2 rows in set (0.03 sec)

注意: 多个select后的字段列表中字段数量应该一直。


在些情况下两查询的结果会存在重合,若我们不想有重复数据可以去掉union后的all


子查询


标量子查询


select * from 表1 where a = (select a from 表2 where 条件);

如果我们要查询user表中id为1的人对应foot表中的水果。

mysql> select user.foot_id from user where id = 1; 
+---------+
| foot_id |
+---------+
|       1 |
+---------+
1 row in set (0.03 sec)
mysql> select foot.s from foot where id = 1;
+------+
| s    |
+------+
| 苹果 |
+------+
1 row in set (0.02 sec)
// 标量子查询
mysql>  select foot.s from foot where id = (select user.foot_id from user where id = 1);
+------+
| s    |
+------+
| 苹果 |
+------+
1 row in set (0.04 sec)

列子查询


子查询中数据为列。


select * from 表1 where a in (select a from 表2 where 条件)

select * from 表1 where a > all/some/any(select b from 表2 where 条件);

常用in/not in/any/some/all,其中any和some时一样的效果。


查询user表中在foot表有对应信息的信息。

mysql> select * from user where id in (select foot.id from foot);
+----+------+--------+---------+
| id | name | gender | foot_id |
+----+------+--------+---------+
|  1 | ton  | 男     |       1 |
|  2 | bom  | 女     |       2 |
|  3 | lin  | 男     |       3 |
+----+------+--------+---------+
3 rows in set (0.02 sec)

行子查询


子查询中数据为行。


select * from 表名 where (a,b) = (select a,b from where 条件);

mysql> select * from user;
+----+------+--------+---------+
| id | name | gender | foot_id |
+----+------+--------+---------+
|  1 | 张三 | 男     |       1 |
|  2 | 李四 | 女     |       2 |
|  3 | 王五 | 男     |       3 |
|  4 | 熊大 | 女     | NULL    |
+----+------+--------+---------+
4 rows in set (0.03 sec)
mysql> select * from yg;
+----+------+------+
| id | name | t_id |
+----+------+------+
|  1 | 张三 | NULL |
|  2 | 李四 |    1 |
|  3 | 王五 |    1 |
+----+------+------+
3 rows in set (0.03 sec)
//行子查询
mysql> select * from user where (id,name) in (select yg.id,yg.name from yg);
+----+------+--------+---------+
| id | name | gender | foot_id |
+----+------+--------+---------+
|  1 | 张三 | 男     |       1 |
|  2 | 李四 | 女     |       2 |
|  3 | 王五 | 男     |       3 |
+----+------+--------+---------+
3 rows in set (0.03 sec)


表子查询


select * from 表名 where (a,b) in (select a,b from 表名 where name = 'bom' or name = 'tom');

mysql> select * from user where (user.id,user.name) in (select yg.id,yg.name from yg where name = '张三' or name = '王五');
+----+------+--------+---------+
| id | name | gender | foot_id |
+----+------+--------+---------+
|  1 | 张三 | 男     |       1 |
|  3 | 王五 | 男     |       3 |
+----+------+--------+---------+
2 rows in set (0.04 sec)

也可以把查询后的子表当主句查询表,例如:


select e.* , d.* from (select * from 表名 where date > '2006-5-23') e left join dept d on e.dept_id = d.id;


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3月前
|
关系型数据库 MySQL Java
centos7安装mysql教程及Navicat平替软件
【8月更文挑战第17天】本教程详述CentOS 7上安装MySQL的过程。首先确保移除任何预装的MySQL组件,然后通过wget获取并安装MySQL的YUM源。可以选择安装特定版本如5.7或8.0。安装MySQL服务器后,启动服务并查找初始密码。登录MySQL后应立即更改密码,并可根据需要设置远程访问权限。此外,还推荐使用免费开源的DBeaver作为数据库管理工具,提供了安装步骤以方便管理和操作MySQL数据库。
148 3
|
30天前
|
存储 SQL 关系型数据库
【入门级教程】MySQL:从零开始的数据库之旅
本教程面向零基础用户,采用通俗易懂的语言和丰富的示例,帮助你快速掌握MySQL的基础知识和操作技巧。内容涵盖SQL语言基础(SELECT、INSERT、UPDATE、DELETE等常用语句)、使用索引提高查询效率、存储过程等。适合学生、开发者及数据库爱好者。
40 0
【入门级教程】MySQL:从零开始的数据库之旅
|
1月前
|
tengine 关系型数据库 MySQL
Tengine、Nginx安装MySQL数据库命令教程
本指南详细介绍了在Linux系统上安装与配置MySQL数据库的步骤。首先通过下载并安装MySQL社区版本,接着启动MySQL服务,使用`systemctl start mysqld.service`命令。若启动失败,可尝试使用`sudo /etc/init.d/mysqld start`。利用`systemctl status mysqld.service`检查MySQL的服务状态,确保其处于运行中。通过日志文件获取初始密码,使用该密码登录数据库,并按要求更改初始密码以增强安全性。随后创建一个名为`tengine`的数据库,最后验证数据库创建是否成功以及完成整个设置流程。
|
3月前
|
SQL 关系型数据库 MySQL
PHP与MySQL交互之基础教程
【8月更文挑战第31天】 在数字世界中,数据是推动一切的核心力量。本文将引导你探索PHP与MySQL的协同工作,通过实际代码示例,展示如何建立连接、执行查询以及处理结果集。无论你是初学者还是希望巩固知识的开发者,这篇文章都将为你提供宝贵的实践知识。
|
3月前
|
关系型数据库 MySQL 网络安全
MySQL主从复制详细教程
配置MySQL的主从复制是一个细致的过程,需要仔细遵循上述步骤进行。一旦配置完成并运行正常,主从复制将大大提高数据库的可用性和读写性能。在操作过程中,务必保持谨慎,确保数据的一致性和安全性。
378 0
|
4月前
|
关系型数据库 MySQL Linux
Docker安装mysql详细教程, mysqld: Can‘t read dir of ‘/etc/mysql/conf.d/‘(报错已解决)
Docker安装mysql详细教程, mysqld: Can't read dir of '/etc/mysql/conf.d/' (Errcode: 2 - No such file or directory) 已解决
|
4月前
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
306 3
|
4月前
|
关系型数据库 MySQL 数据库
MySQL 保姆级教程(八):创建计算字段
MySQL 保姆级教程(八):创建计算字段
|
4月前
|
关系型数据库 MySQL
MySQL 保姆级教程(五):数据过滤
MySQL 保姆级教程(五):数据过滤
|
4月前
|
关系型数据库 MySQL
MySQL 保姆级教程(四):过滤数据
MySQL 保姆级教程(四):过滤数据