数据库中的 Join 操作

Contents
Warning
This article was last updated on 2022-05-26, the content may be out of date.

数据库结构查询语句中 7 种 Join 操作详解。

表结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
create table if not exists `a`(
    `id` int auto_increment,
    `astr1` varchar(4),
    `astr2` varchar(4),
    `bid` int,
    primary key (`id`)
);
create table if not exists `b`(
    `id` int auto_increment,
    `bstr1` varchar(4),
    `bstr2` varchar(4),
    primary key (`id`)
);

表 a

idastr1astr2bid
1AAA1
2BBB2
3CCC3
4DDD4
5EEE1
6FFF2
7XXX11
8YYY12
9ZZZ11

表 b

idbstr1bstr2
1aaa
2bbb
3ccc
4ddd
5eee
6fff
7xxx
8yyy
9zzz

A ∩ B

使用 inner join

1
2
3
4
select *
from a
inner join b
on a.bid=b.id;

也可使用笛卡尔乘积,然后指定条件

1
2
3
select *
from a,b
where a.bid=b.id;

inner join 结果

a.idastr1astr2bidb.idbstr1bstr2
1AAA11aaa
2BBB22bbb
3CCC33ccc
4DDD44ddd
5EEE11aaa
6FFF22bbb

结果显示:

  • 若 a.bid 中有在 b.id 中找不到的记录,丢弃
  • 若 b.id 中有在 a.bid 中找不到的记录,丢弃
  • 在 a.bid 和 b.id 都存在的记录,保留
结果是否包含记录b.id 有b.id 无
a.bid 有
a.bid 无-

A (A ∩ B + A*)

使用 left join

1
2
3
4
select *
from a
left join b
on a.bid=b.id;

left join 结果

a.idastr1astr2bidb.idbstr1bstr2
1AAA11aaa
2BBB22bbb
3CCC33ccc
4DDD44ddd
5EEE11aaa
6FFF22bbb
7XXX11NULLNULLNULL
8YYY12NULLNULLNULL
9ZZZ11NULLNULLNULL

结果显示:

  • 若 a.bid 中有在 b.id 中找不到的记录,保留
  • 若 b.id 中有在 a.bid 中找不到的记录,丢弃
  • 在 a.bid 和 b.id 都存在的记录,保留
结果是否包含记录b.id 有b.id 无
a.bid 有
a.bid 无-

B (A ∩ B + B*)

使用 right join

1
2
3
4
select *
from a
right join b
on a.bid=b.id;

right join 结果

a.idastr1astr2bidb.idbstr1bstr2
5EEE11aaa
1AAA11aaa
6FFF22bbb
2BBB22bbb
3CCC33ccc
4DDD44ddd
NULLNULLNULLNULL5eee
NULLNULLNULLNULL6fff
NULLNULLNULLNULL7xxx
NULLNULLNULLNULL8yyy
NULLNULLNULLNULL9zzz

结果显示:

  • 若 a.bid 中有在 b.id 中找不到的记录,丢弃
  • 若 b.id 中有在 a.bid 中找不到的记录,保留
  • 在 a.bid 和 b.id 都存在的记录,保留
结果是否包含记录b.id 有b.id 无
a.bid 有
a.bid 无-

A* (A - A ∩ B)

使用 left join

1
2
3
4
5
select *
from a
left join b
on a.bid=b.id
where b.id is null;

A* left join 结果

a.idastr1astr2bidb.idbstr1bstr2
7XXX11NULLNULLNULL
8YYY12NULLNULLNULL
9ZZZ11NULLNULLNULL

结果显示:

  • 若 a.bid 中有在 b.id 中找不到的记录,保留
  • 若 b.id 中有在 a.bid 中找不到的记录,丢弃
  • 在 a.bid 和 b.id 都存在的记录,丢弃
结果是否包含记录b.id 有b.id 无
a.bid 有
a.bid 无-

B* (B - A ∩ B)

使用 right join

1
2
3
4
5
select *
from a
right join b
on a.bid=b.id
where a.bid is null;

B* right join 结果

a.idastr1astr2bidb.idbstr1bstr2
NULLNULLNULLNULL5eee
NULLNULLNULLNULL6fff
NULLNULLNULLNULL7xxx
NULLNULLNULLNULL8yyy
NULLNULLNULLNULL9zzz

结果显示:

  • 若 a.bid 中有在 b.id 中找不到的记录,丢弃
  • 若 b.id 中有在 a.bid 中找不到的记录,保留
  • 在 a.bid 和 b.id 都存在的记录,丢弃
结果是否包含记录b.id 有b.id 无
a.bid 有
a.bid 无-

A ∪ B

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
-- 仅 Oracle 支持
select *
from a
full outer join b
on a.bid=b.id;

-- MySQL 写法
select *
from a
left join b
on a.bid=b.id
union
select *
from a
right join b
on a.bid=b.id;

outer join 结果

a.idastr1astr2bidb.idbstr1bstr2
1AAA11aaa
2BBB22bbb
3CCC33ccc
4DDD44ddd
5EEE11aaa
6FFF22bbb
7XXX11NULLNULLNULL
8YYY12NULLNULLNULL
9ZZZ11NULLNULLNULL
NULLNULLNULLNULL5eee
NULLNULLNULLNULL6fff
NULLNULLNULLNULL7xxx
NULLNULLNULLNULL8yyy
NULLNULLNULLNULL9zzz

结果显示:

  • 若 a.bid 中有在 b.id 中找不到的记录,保留
  • 若 b.id 中有在 a.bid 中找不到的记录,保留
  • 在 a.bid 和 b.id 都存在的记录,保留
结果是否包含记录b.id 有b.id 无
a.bid 有
a.bid 无-
提示
  • JOIN 相当于表的横向连接
  • UNION 相当于表的纵向连接
  • UNION 在两表的字段没有相同时会报错,所以不要直接使用 select * from a UNION select * from b

A ∪ B - A ∩ B

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
-- 仅 Oracle 支持
select *
from a
full outer join b
on a.bid=b.id
where a.bid is null or b.id is null;

-- MySQL 写法
select *
from a
left join b
on a.bid=b.id
where b.id is null
union
select *
from a
right join b
on a.bid=b.id
where a.bid is null;

full outer join 结果

a.idastr1astr2bidb.idbstr1bstr2
7XXX11NULLNULLNULL
8YYY12NULLNULLNULL
9ZZZ11NULLNULLNULL
NULLNULLNULLNULL5eee
NULLNULLNULLNULL6fff
NULLNULLNULLNULL7xxx
NULLNULLNULLNULL8yyy
NULLNULLNULLNULL9zzz

结果显示:

  • 若 a.bid 中有在 b.id 中找不到的记录,保留
  • 若 b.id 中有在 a.bid 中找不到的记录,保留
  • 在 a.bid 和 b.id 都存在的记录,保留
结果是否包含记录b.id 有b.id 无
a.bid 有
a.bid 无-

总结

数据库的七种 JOIN 操作分别是作为两个表 连接字段记录集合 A 、 B 的七种操作关系,对应下图:

SQLJoin 操作

Update Available

A new version of this site is available.