1.1 笛卡尔积
1.1.1 概述
笛卡尔乘积是指在数学中,两个集合 X 和 Y 的笛卡尔积(Cartesian product),又称直积,表示为 X×Y,第一个对象是 X 的成员而第二个对象是 Y 的所有可能有序对的其中一个成员。假设集合 A={a, b},集合 B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。
1.1.2 数据准备
代码语言:javascript复制mysql> select * from dept;
--------- -----------
| dept_id | dept_name |
--------- -----------
| 1 | 技术部 |
| 2 | NULL |
| NULL | 财务部 |
| 4 | 办公室 |
| 5 | 运营部 |
| 6 | NULL |
--------- -----------
6 rows in set (0.06 sec)
mysql> select * from emp;
-------- ----------
| emp_id | emp_name |
-------- ----------
| 1 | 张三 |
| 2 | 李四 |
| 3 | NULL |
| 4 | 马六 |
| NULL | 田七 |
-------- ----------
5 rows in set (0.05 sec)
1.1.3 MySQL 中的笛卡尔积
代码语言:javascript复制# 第一种方式
select * from tb_name_1, tb_name_2, ···;
# 第二种方式
select * from tb_name_1 join tb_name_2 join ···;
1.1.4 示例
代码语言:javascript复制mysql> select * from dept, emp;
--------- ----------- -------- ----------
| dept_id | dept_name | emp_id | emp_name |
--------- ----------- -------- ----------
| 1 | 技术部 | 1 | 张三 |
| 1 | 技术部 | 2 | 李四 |
| 1 | 技术部 | 3 | NULL |
| 1 | 技术部 | 4 | 马六 |
| 1 | 技术部 | NULL | 田七 |
| 2 | NULL | 1 | 张三 |
| 2 | NULL | 2 | 李四 |
| 2 | NULL | 3 | NULL |
| 2 | NULL | 4 | 马六 |
| 2 | NULL | NULL | 田七 |
| NULL | 财务部 | 1 | 张三 |
| NULL | 财务部 | 2 | 李四 |
| NULL | 财务部 | 3 | NULL |
| NULL | 财务部 | 4 | 马六 |
| NULL | 财务部 | NULL | 田七 |
| 4 | 办公室 | 1 | 张三 |
| 4 | 办公室 | 2 | 李四 |
| 4 | 办公室 | 3 | NULL |
| 4 | 办公室 | 4 | 马六 |
| 4 | 办公室 | NULL | 田七 |
| 5 | 运营部 | 1 | 张三 |
| 5 | 运营部 | 2 | 李四 |
| 5 | 运营部 | 3 | NULL |
| 5 | 运营部 | 4 | 马六 |
| 5 | 运营部 | NULL | 田七 |
| 6 | NULL | 1 | 张三 |
| 6 | NULL | 2 | 李四 |
| 6 | NULL | 3 | NULL |
| 6 | NULL | 4 | 马六 |
| 6 | NULL | NULL | 田七 |
--------- ----------- -------- ----------
30 rows in set (0.05 sec)
1.2 内连接
内连接也叫连接,是最早的一种连接。还可以被称为普通连接或者自然连接,内连接是从结果表中删除与其他被连接表中没有匹配行的所有行,所以内连接可能会丢失信息。内连接相当于在笛卡尔积的基础上加上了连接的条件;当没有连接条件的时候,内连接上升为笛卡尔积。
1.2.1 语法
代码语言:javascript复制# 第一种方式(显示内连接),inner 可以省略,condition 为连接条件
select * from tb_name_1 [inner] join tb_name_2 on condition;
# 第二种方式(隐式内连接)
select * from tb_name_1, tb_name_2 where condition;
☞ 说明
① 第一种是在 on 后使用了连接条件 ② 第二种是先获取连接的结果,然后使用 where 中的条件再对连接结果进行过滤 ③ 内连接查询的数据不包含连接条件字段为 null 的数据
1.2.2 示例
代码语言:javascript复制mysql> select * from dept join emp on dept.dept_id = emp.emp_id;
--------- ----------- -------- ----------
| dept_id | dept_name | emp_id | emp_name |
--------- ----------- -------- ----------
| 1 | 技术部 | 1 | 张三 |
| 2 | NULL | 2 | 李四 |
| 4 | 办公室 | 4 | 马六 |
--------- ----------- -------- ----------
3 rows in set (0.05 sec)
1.3 外连接
外连接涉及到 2 个表,主表和从表,要查询的信息主要来自于哪个表,谁就是主表。外连接查询结果为主表中所有记录。如果从表中有和它匹配的,则显示匹配的值,这部分相当于内连接查询出来的结果;如果从表中没有和它匹配的,则显示null。
1.3.1 左外连接
☞ 语法
代码语言:javascript复制# 左外链接使用 left join 关键字,left join 左边的是主表,outer 可以省略
select * from tb_name_1 left [outer] join tb_name_2 on condition;
☞ 示例
代码语言:javascript复制mysql> select * from dept left join emp on dept.dept_id = emp.emp_id;
--------- ----------- -------- ----------
| dept_id | dept_name | emp_id | emp_name |
--------- ----------- -------- ----------
| 1 | 技术部 | 1 | 张三 |
| 2 | NULL | 2 | 李四 |
| 4 | 办公室 | 4 | 马六 |
| NULL | 财务部 | NULL | NULL |
| 5 | 运营部 | NULL | NULL |
| 6 | NULL | NULL | NULL |
--------- ----------- -------- ----------
6 rows in set (0.05 sec)
1.3.2 右外连接
☞ 语法
代码语言:javascript复制# 右外连接使用 right join关键字,right join 右边的是主表,outer 可以省略
select * from tb_name_1 right [outer] join tb_name_2 on condition;
☞ 示例
代码语言:javascript复制mysql> select * from emp left join dept on dept.dept_id = emp.emp_id;
-------- ---------- --------- -----------
| emp_id | emp_name | dept_id | dept_name |
-------- ---------- --------- -----------
| 1 | 张三 | 1 | 技术部 |
| 2 | 李四 | 2 | NULL |
| 4 | 马六 | 4 | 办公室 |
| 3 | NULL | NULL | NULL |
| NULL | 田七 | NULL | NULL |
-------- ---------- --------- -----------
5 rows in set (0.05 sec)
☞ 注意
左外连接和右外连接看似可以互换,但是要考虑大小表问题,如:(小表 左连 大表) (大表 右连 小表)二者之间的效率天差地别,推荐左边的表使用小表。