MySQL必知必会 -- 联结表

  • 外键(foreign key) 外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系。

使用联结表的优点:

  • 信息不重复,从而不浪费时间和空间;
  • 如果信息变动,可以只更新表中的单个记录,相关表中的数据不用改动;
  • 由于数据无重复,显然数据是一致的,这使得处理数据更简单。

联结表的使用

MariaDB [test]> select * from users;
+-------+--------+------+------+-------+------------+-------+
| user  | passwd | sex  | age  | price | math_price | class |
+-------+--------+------+------+-------+------------+-------+
| user2 | 222    | girl | 23   | 155   | 36         |     1 |
| user3 | 333    | boy  | 12   | 78    | 66         |     1 |
| user4 | 444    | boy  | 22   | NULL  | NULL       |     2 |
| user5 | 555    | boy  | 30   | NULL  | 43         |     2 |
| user1 | 111    | boy  | 18   | 35    | 88         |     1 |
| user6 | 666    | girl | 16   | 35    | 43         |     2 |
+-------+--------+------+------+-------+------------+-------+
6 rows in set (0.01 sec)

MariaDB [test]> select * from hour;
+-------+-------+
| hours | user  |
+-------+-------+
|    12 | user2 |
|     8 | user6 |
|     9 | user1 |
|    11 | user3 |
|    10 | user4 |
|    10 | user5 |
+-------+-------+
6 rows in set (0.00 sec)

MariaDB [test]> select class,sex,hours from users,hour where hour.user = users.user order by class;
+-------+------+-------+
| class | sex  | hours |
+-------+------+-------+
|     1 | boy  |    11 |
|     1 | girl |    12 |
|     1 | boy  |     9 |
|     2 | boy  |    10 |
|     2 | boy  |    10 |
|     2 | girl |     8 |
+-------+------+-------+
6 rows in set (0.00 sec)

这里所指定的两个列(class,sex)在users表中,而另一个列(hours)在 hour表中。这两个表用WHERE子句正确联结,WHERE 就是他们的联结条件.

没有联结条件的表关系返回的结果为笛卡儿积。

检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。

内联结

对于上面的查询语句,我们可以用内联结的方式表示:
在这里插入图片描述
这里使用innor join 的方式联结,用 ON 进行筛选。

多表联结

SQL对一条SELECT语句中可以联结的表的数目没有限制。创建联结的基本规则也相同。
首先列出所有表,然后定义表之间的关系。
在这里插入图片描述

创建高级联结

使用表别名

MariaDB [test]> select  u.class,u.sex,h.hours from users as u,hour as h where u.user = h.user;
+-------+------+-------+
| class | sex  | hours |
+-------+------+-------+
|     1 | girl |    12 |
|     2 | girl |     8 |
|     1 | boy  |     9 |
|     1 | boy  |    11 |
|     2 | boy  |    10 |
|     2 | boy  |    10 |
+-------+------+-------+
6 rows in set (0.00 sec)

这种方式可以缩短SQL语句;并允许在单条SELECT语句中多次使用相同的表

使用不同类型的联结

自联结

一直有一位同学请假,找出同一班中其他的同学是否请假,我们首先要找出这个班的其他同学;

ariaDB [test]> select user,sex,math_price from users where class = (select class from users where user = 'user1');
+-------+------+------------+
| user  | sex  | math_price |
+-------+------+------------+
| user2 | girl | 36         |
| user3 | boy  | 66         |
| user1 | boy  | 88         |
+-------+------+------------+
3 rows in set (0.00 sec)

这是第一种解决方案,它使用了子查询,那么我们是用自联结如何解决。

MariaDB [test]> select u1.user,u1.sex,u1.math_price 
				from users as u1,users as u2 
				where u1.class = u2.class and u2.user =  'user1';

-------+------+------------+
| user  | sex  | math_price |
+-------+------+------------+
| user2 | girl | 36         |
| user3 | boy  | 66         |
| user1 | boy  | 88         |
+-------+------+------------+
3 rows in set (0.01 sec)

通常情况下使用自联结的查询速率比使用子查询的速率要快。

自然连接

无论何时对表进行联结,应该至少有一个列出现在不止一个表中(被联结的列)。标准的联结(前一章中介绍的内部联结)返回所有数据,甚至相同的列多次出现。自然联结排除多次出现,使每个列只返回一次。
这项工作,由自己完成。自然联结是这样一种联结,其中你只能选择那些唯一的列。
这一般是通过对表使用通配符(SELECT *),对所有其他表的列使用明确的子集来完成的。

外联结

MariaDB [test]> select * from hour;
+-------+-------+
| hours | user  |
+-------+-------+
|    12 | user2 |
|     8 | user6 |
|     9 | user1 |
|    11 | user3 |
|    10 | user4 |
|    10 | user5 |
|    11 | NULL  |
+-------+-------+
7 rows in set (0.00 sec)

MariaDB [test]> select * from users;
+-------+--------+------+------+-------+------------+-------+
| user  | passwd | sex  | age  | price | math_price | class |
+-------+--------+------+------+-------+------------+-------+
| user2 | 222    | girl | 23   | 155   | 36         |     1 |
| user3 | 333    | boy  | 12   | 78    | 66         |     1 |
| user4 | 444    | boy  | 22   | NULL  | NULL       |     2 |
| user5 | 555    | boy  | 30   | NULL  | 43         |     2 |
| user1 | 111    | boy  | 18   | 35    | 88         |     1 |
| user6 | 666    | girl | 16   | 35    | 43         |     2 |
| user7 | 777    | boy  | NULL | NULL  | NULL       |  NULL |
+-------+--------+------+------+-------+------------+-------+
7 rows in set (0.00 sec)

MariaDB [test]> select users.user,hour.hours from users left join hour on users.user = hour.user;
+-------+-------+
| user  | hours |
+-------+-------+
| user2 |    12 |
| user6 |     8 |
| user1 |     9 |
| user3 |    11 |
| user4 |    10 |
| user5 |    10 |
| user7 |  NULL |
+-------+-------+
7 rows in set (0.00 sec)

MariaDB [test]> select users.user,hour.hours from users right join hour on users.user = hour.user;
+-------+-------+
| user  | hours |
+-------+-------+
| user2 |    12 |
| user3 |    11 |
| user4 |    10 |
| user5 |    10 |
| user1 |     9 |
| user6 |     8 |
| NULL  |    11 |
+-------+-------+
7 rows in set (0.00 sec)

使用了关键字OUTER JOIN来指定联结的类型,outer 可以省略,并且必须加上 LEFT 或RIGHT 指明方向。
左联结会打印出左边表的所有行,二右联结会打印出右边表的所有行。

使用带聚集函数的联结

如果要检索所有客户及每个客户所下的订单数,下面使用了COUNT()函数的代码可完成此工作:
在这里插入图片描述

使用联结和联结条件

  • 注意所使用的联结类型。一般我们使用内部联结,但使用外部联结也是有效的。
  • 保证使用正确的联结条件,否则将返回不正确的数据。
  • 应该总是提供联结条件,否则会得出笛卡儿积。
  • 在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在一起测试它们前,分别测试每个联结。这将使故障排除更为简单。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值