第 15 章 联结表
15.1 联结
SQL 最强大的功能之一就是能在数据检索查询的执行中联结表
15.1.1 关系表
关系表的设计就是要保证把信息分解成多个表,一类数据一个表。各表通过某些常用的值(即关系设计中的关系)互相关联
外键:为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系
可伸缩性:能够适应不断增加的工作量而不失败
15.1.2 为什么要使用联结
联结是一种机制,用来在一条 SELECT 语句中关联表,使用特殊语法可以联结多个表返回一组输出,联结在运行时关联表中正确的行
15.2 创建联结
输入: SELECT innodb_table_stats.database_name,n_rows,stat_name FROM innodb_table_stats,innodb_index_stats WHERE innodb_table_stats.table_name = innodb_index_stats.table_name;
输出:
+---------------+--------+--------------+
| database_name | n_rows | stat_name |
+---------------+--------+--------------+
| crashcourse | 5 | n_diff_pfx01 |
| crashcourse | 5 | n_leaf_pages |
| crashcourse | 5 | size |
| crashcourse | 0 | n_diff_pfx01 |
| crashcourse | 0 | n_diff_pfx02 |
| crashcourse | 0 | n_leaf_pages |
| crashcourse | 0 | size |
| crashcourse | 0 | n_diff_pfx01 |
| crashcourse | 0 | n_diff_pfx02 |
| crashcourse | 0 | n_diff_pfx03 |
| crashcourse | 0 | n_leaf_pages |
| crashcourse | 0 | size |
| crashcourse | 5 | n_diff_pfx01 |
| crashcourse | 5 | n_leaf_pages |
| crashcourse | 5 | size |
| crashcourse | 5 | n_diff_pfx01 |
| crashcourse | 5 | n_diff_pfx02 |
| crashcourse | 5 | n_leaf_pages |
| crashcourse | 5 | size |
| crashcourse | 0 | n_diff_pfx01 |
| crashcourse | 0 | n_leaf_pages |
| crashcourse | 0 | size |
| crashcourse | 0 | n_diff_pfx01 |
| crashcourse | 0 | n_diff_pfx02 |
| crashcourse | 0 | n_leaf_pages |
| crashcourse | 0 | size |
| crashcourse | 6 | n_diff_pfx01 |
| crashcourse | 6 | n_leaf_pages |
| crashcourse | 6 | size |
| mysql | 0 | n_diff_pfx01 |
| mysql | 0 | n_leaf_pages |
| mysql | 0 | size |
| sys | 6 | n_diff_pfx01 |
| sys | 6 | n_leaf_pages |
| sys | 6 | size |
+---------------+--------+--------------+
分析: FROM 列出了两个表,它们就是所联结的表,这两个表用 WHERE 子句正确联结
15.2.1 WHERE 子句的重要性
笛卡儿积: 由没有联结条件的表关系返回的结果为笛卡儿积,检索出的行的数目将时第一个表中的行数乘第二个表中的行数。拿上面例子举例👇
输入: SELECT innodb_table_stats.database_name,n_rows,stat_name FROM innodb_table_stats,innodb_index_stats;
输出:
………………………………………………(此处省略返回结果)
245 rows in set (0.00 sec)
分析: 可以看到返回结果明显不同,数据多的多,这并不是我们所想要的,应该保证所有联结都有 WHERE 子句
15.2.2 内部联结
目前为止所用的联结称为等值联结,它基于两个表之间的相等测试,也被称为内部联结。其实对于这种联结可以使用稍微不同的语法来明确指定联结的类型,如下所示
输入: SELECT innodb_table_stats.database_name,n_rows,stat_name FROM innodb_table_stats INNER JOIN innodb_index_stats ON innodb_table_stats.table_name = innodb_index_stats.table_name;
输出:
+---------------+--------+--------------+
| database_name | n_rows | stat_name |
+---------------+--------+--------------+
| crashcourse | 5 | n_diff_pfx01 |
| crashcourse | 5 | n_leaf_pages |
| crashcourse | 5 | size |
| crashcourse | 0 | n_diff_pfx01 |
| crashcourse | 0 | n_diff_pfx02 |
| crashcourse | 0 | n_leaf_pages |
| crashcourse | 0 | size |
| crashcourse | 0 | n_diff_pfx01 |
| crashcourse | 0 | n_diff_pfx02 |
| crashcourse | 0 | n_diff_pfx03 |
| crashcourse | 0 | n_leaf_pages |
| crashcourse | 0 | size |
| crashcourse | 5 | n_diff_pfx01 |
| crashcourse | 5 | n_leaf_pages |
| crashcourse | 5 | size |
| crashcourse | 5 | n_diff_pfx01 |
| crashcourse | 5 | n_diff_pfx02 |
| crashcourse | 5 | n_leaf_pages |
| crashcourse | 5 | size |
| crashcourse | 0 | n_diff_pfx01 |
| crashcourse | 0 | n_leaf_pages |
| crashcourse | 0 | size |
| crashcourse | 0 | n_diff_pfx01 |
| crashcourse | 0 | n_diff_pfx02 |
| crashcourse | 0 | n_leaf_pages |
| crashcourse | 0 | size |
| crashcourse | 6 | n_diff_pfx01 |
| crashcourse | 6 | n_leaf_pages |
| crashcourse | 6 | size |
| mysql | 0 | n_diff_pfx01 |
| mysql | 0 | n_leaf_pages |
| mysql | 0 | size |
| sys | 6 | n_diff_pfx01 |
| sys | 6 | n_leaf_pages |
| sys | 6 | size |
+---------------+--------+--------------+
分析:这里两个表之间的关系是 FROM 子句的组成部分,以 INNER JOIN 指定。在使用这种语法时,联结条件用特定的 ON 子句而不是 WHERE 子句给出。传递给 ON 的实际条件与传递给 WHERE 的相同
SQL 规范首选 INNER JOIN ON 语法
15.2.3 联结多个表
输入: SELECT innodb_table_stats.database_name,n_rows,stat_name FROM innodb_table_stats INNER JOIN innodb_index_stats ON innodb_table_stats.table_name = innodb_index_stats.table_name INNER JOIN db ON db.Db = innodb_table_stats.database_name;
输出:
+---------------+--------+--------------+
| database_name | n_rows | stat_name |
+---------------+--------+--------------+
| sys | 6 | n_diff_pfx01 |
| sys | 6 | n_leaf_pages |
| sys | 6 | size |
+---------------+--------+--------------+