从多个表中查询数据
-
有些查询需要来自多个表的数据
-
可以使用join操作来合并来自不同表的数据
-
要联接表,这些表中的某些列之间应当存在逻辑关系
-
最佳实现:使用表明别名
-
示例
mysql> select * from a;
+------+------+
| id | name |
+------+------+
| 1 | AA |
| 2 | BB |
| 3 | AC |
+------+------+
3 rows in set (0.01 sec)
mysql> select * from b;
+------+------+
| id | name |
+------+------+
| 1 | BA |
| 2 | BB |
| 3 | BC |
+------+------+
3 rows in set (0.02 sec)
mysql> select * from c;
+------+------+
| id | name |
+------+------+
| 1 | CA |
| 2 | CB |
| 4 | CC |
+------+------+
3 rows in set (0.01 sec)
mysql> select * from d;
+------+------+
| id | name |
+------+------+
| 1 | DA |
| 2 | DB |
| NULL | DC |
| 5 | NULL |
+------+------+
4 rows in set (0.00 sec)
笛卡尔积
- 使用join关键字,但是没有join条件
mysql> select a.name,b.name from a a join b b ;
±-----±-----+
| name | name |
±-----±-----+
| AA | BC |
| AA | BB |
| AA | BA |
| BB | BC |
| BB | BB |
| BB | BA |
| AC | BC |
| AC | BB |
| AC | BA |
±-----±-----+
9 rows in set (0.09 sec)
inner join(内连接)
mysql> select a.name,b.name from a a join b b on a.id=b.id;
+------+------+
| name | name |
+------+------+
| AA | BA |
| BB | BB |
| AC | BC |
+------+------+
3 rows in set (0.05 sec)
mysql> select a.name,c.name from a a join c c on a.id=c.id;
+------+------+
| name | name |
+------+------+
| AA | CA |
| BB | CB |
+------+------+
2 rows in set (0.01 sec)
mysql> select a.name,d.name from a a join d d on a.id=d.id;
+------+------+
| name | name |
+------+------+
| AA | DA |
| BB | DB |
+------+------+
2 rows in set (0.00 sec)
外连接
- 左外连接
mysql> select a.name,c.name from a a left join c c on a.id=c.id;
+------+------+
| name | name |
+------+------+
| AA | CA |
| BB | CB |
| AC | NULL |
+------+------+
3 rows in set (0.02 sec)
- 右外连接
mysql> select a.name,c.name from a a right join c c on a.id=c.id;
+------+------+
| name | name |
+------+------+
| AA | CA |
| BB | CB |
| NULL | CC |
+------+------+
3 rows in set (0.00 sec)
外连接和NULL
- null 在外连接中的行为:
mysql> select a.name,d.name from a a right join d d on a.id=d.id;
+------+------+
| name | name |
+------+------+
| AA | DA |
| BB | DB |
| NULL | DC |
| NULL | NULL |
+------+------+
4 rows in set (0.00 sec)
mysql> select a.name,d.name,a.id,d.id from a a right join d d on
a.id=d.id;
+------+------+------+------+
| name | name | id | id |
+------+------+------+------+
| AA | DA | 1 | 1 |
| BB | DB | 2 | 2 |
| NULL | DC | NULL | NULL |
| NULL | NULL | NULL | 5 |
+------+------+------+------+
4 rows in set (0.01 sec)
UNION
- 使用UNION关键字将来自多个SELECT 语句的结果合并到单个结果集中
- 每个SELECT 语句种的列数必须相同
- 每个SELECT语句处于相同位置的列必须是兼容的数据类型
- 默认为union DISTINCT,表示去重
- UNION ALL保留重复的记录
- 语法
query_1
union [ALL | DISTINCT]
query _2
mysql> select id from a union select id from b;
+------+
| id |
+------+
| 2 |
| 1 |
| 3 |
+------+
3 rows in set (0.00 sec)
mysql> select id from a union all select id from b;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 1 |
| 2 |
| 3 |
+------+
6 rows in set (0.02 sec)
差集(except)和交集(intersect)
mysql> select id from a except select id from c;
+------+
| id |
+------+
| 3 |
+------+
1 row in set (0.01 sec)
mysql> select id from c except select id from a;
+------+
| id |
+------+
| 4 |
+------+
1 row in set (0.00 sec)
mysql> select id from d except select id from a;
+------+
| id |
+------+
| 5 |
| NULL |
+------+
2 rows in set (0.01 sec)
mysql> (select id from d except select id from a) order by id;
+------+
| id |
+------+
| NULL |
| 5 |
+------+
2 rows in set (0.00 sec)
with 语句
针对复杂逻辑的SQL语句,with可以大幅减少临时表的数量。提升SQL代码的可读性和可维护性
with low_g_planets as (
select p.id,p.name,p.gravity
from starts s
join planets p
on p.sun_id = s.id
where s.name = 'Sun' and p.gravity<10)
select v1.name,v1.gravity,m.name from low_g_planets as v1 left join moons m on v1.id=m.planet_id;