MySQL操作实战(三):表联结-LMLPHP

1. 简单联结

①内部联结

内部联结又称为等值联结。ANSI SQL规范首选INNER JOIN语法
内部联结分为隐式内联结显式内联结,二者查询效果相同,仅仅是语法不一样而已。

  • 应用场景:统计参加了考试的学生及其各科成绩
# 隐式内联结
mysql> SELECT a.stu_id, stu_name, a.lesson_id, lesson_name, score
    -> FROM t_score a, t_stu_profile b, t_lesson c
    -> WHERE a.stu_id = b.stu_id AND a.lesson_id = c.lesson_id
    -> ORDER BY stu_id, lesson_id
    -> ;
+--------+----------+-----------+-------------+-------+
| stu_id | stu_name | lesson_id | lesson_name | score |
+--------+----------+-----------+-------------+-------+
|      1 | 郭东     | L001      | 语文        |    90 |
|      1 | 郭东     | L002      | 数据        |    86 |
|      2 | 李西     | L001      | 语文        |    84 |
|      2 | 李西     | L002      | 数据        |    90 |
|      2 | 李西     | L003      | 英语        |    86 |
|      2 | 李西     | L004      | 物理        |    75 |
|      2 | 李西     | L005      | 化学        |    77 |
|      3 | 张北     | L001      | 语文        |   100 |
|      3 | 张北     | L002      | 数据        |    91 |
|      3 | 张北     | L003      | 英语        |    85 |
|      4 | 钱南     | L001      | 语文        |    99 |
|      4 | 钱南     | L002      | 数据        |    88 |
|      4 | 钱南     | L003      | 英语        |    66 |
|      4 | 钱南     | L005      | 化学        |    98 |
+--------+----------+-----------+-------------+-------+

# 显式内联结
mysql> SELECT a.stu_id, stu_name, a.lesson_id, lesson_name, score
    -> FROM t_score a
    -> INNER JOIN t_stu_profile b
    -> INNER JOIN t_lesson c
    -> ON a.stu_id = b.stu_id AND a.lesson_id = c.lesson_id
    -> ORDER BY stu_id, lesson_id
    -> ;

2. 高级联结

①自联结

自联结通常作为外部语句用来替代从相同表中检索数据时使用的子查询语句。虽然最终的结果是相同的,但有时候处理联结远比处理子查询快得多。

  • 应用场景:发现成绩表上有个100分的成绩存在问题,需查询100分的这门课程的其它同学的成绩是否存在问题
mysql> SELECT stu_id, score
    -> FROM t_score
    -> WHERE lesson_id = (
    ->     SELECT lesson_id
    ->     FROM t_score
    ->     WHERE score = 100)
    -> ;
+--------+-------+
| stu_id | score |
+--------+-------+
|      1 |    98 |
|      2 |    84 |
|      3 |   100 |
|      4 |    99 |
+--------+-------+
mysql> SELECT a.stu_id, a.score
    -> FROM t_score a, t_score b
    -> WHERE a.lesson_id = b.lesson_id AND b.score = 100
    -> ;
+--------+-------+
| stu_id | score |
+--------+-------+
|      1 |    98 |
|      2 |    84 |
|      3 |   100 |
|      4 |    99 |
+--------+-------+
②自然联结

无论何时对表进行联结,应该至少有一个列出现在不止一个表中(被联结的列)。标准的联结返回所有数据,甚至相同的列多次出现。
自然联结排除多次出现,使每个列只返回一次。

mysql> SELECT b.*, a.lesson_id, c.lesson_name, a.score
    -> FROM t_score a, t_stu_profile b, t_lesson c
    -> WHERE a.stu_id = b.stu_id AND a.lesson_id = c.lesson_id
    -> ;

事实上,迄今为止建立的每个内部联结都是自然联结,很可能永远都不会用到不是自然联结的内部联结。

③外部联结

许多联结将一个表中的行与另一个表中的行相关联,但有时候会需要包含没有关联行的那些行。例如,需要对每个客户下了多少订单进行计数,包括那些至今尚未下订单的客户。
那么,联结包含了那些在相关表中没有关联行的行,这种类型的联结称为外部联结

  • 应用场景:统计每位同学的成绩,包括没参加考试的同学
mysql> SELECT a.stu_id, stu_name, lesson_id, score
    -> FROM t_score a
    -> RIGHT OUTER JOIN t_stu_profile b
    -> ON a.stu_id = b.stu_id
    -> ;
+--------+----------+-----------+-------+
| stu_id | stu_name | lesson_id | score |
+--------+----------+-----------+-------+
|      1 | 郭东     | L001      |    98 |
|      1 | 郭东     | L002      |    86 |
|      1 | 郭东     | L003      |    79 |
|      1 | 郭东     | L004      |    88 |
|      1 | 郭东     | L005      |    98 |
|      2 | 李西     | L001      |    84 |
|      2 | 李西     | L002      |    90 |
|      2 | 李西     | L003      |    86 |
|      2 | 李西     | L004      |    75 |
|      2 | 李西     | L005      |    77 |
|      3 | 张北     | L001      |   100 |
|      3 | 张北     | L002      |    91 |
|      3 | 张北     | L003      |    85 |
|      3 | 张北     | L004      |    79 |
|      3 | 张北     | L005      |    85 |
|      4 | 钱南     | L001      |    99 |
|      4 | 钱南     | L002      |    88 |
|      4 | 钱南     | L003      |    66 |
|      4 | 钱南     | L004      |    66 |
|      4 | 钱南     | L005      |    98 |
|   NULL | 王五     | NULL      |  NULL |
|   NULL | 赵七     | NULL      |  NULL |
+--------+----------+-----------+-------+
02-28 15:08