本章要回答的三个问题:当初为什么要把数据拆进七张表,而不是一张大宽表?INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN 四类连接各自保留哪些行、丢掉哪些行?自连接、多表链与连接条件写错位置,会制造哪些看起来合法、实际错得离谱的结果?学完本章,你能把散落多表的数据拼成一张正确的"宽表"。
前四章的所有查询都困在一张表里,而现实的数据天生散落:书名在 books、分类名在 categories、买家在 customers、成交记录在 orders。想让查询越出单表,得先回答一个更根本的问题——数据为什么长成这个样子?答案叫规范化(范式):把重复出现的信息抽成独立的表,用键建立引用,消除"改一处要改一百处"的维护灾难。理解了拆表的理由,JOIN 就不再是需要死记的语法,而是"把拆开的世界拼回去"的自然动作。
本章的第三小节专门收集"结果合法但数据错误"的连接事故:重复计数、连接条件错位、外连接被 WHERE 条件悄悄废掉武功。这些坑的隐蔽性远高于语法错误——查询能跑、数字能看,就是不对。事故看多了,鉴别力自然就有了。
| 节 | 回答哪个问题 | 关键产出 |
|---|---|---|
| 5.1 为什么拆表:范式与 ER 模型 | 数据为什么长这样 | 三大范式递进、ER 图读法、外键方向判断 |
| 5.2 四类 JOIN 一图选型 | 怎么拼回一张宽表 | 四类连接的行为对照、连接条件与别名规范 |
| 5.3 多表链、自连接与三个事故 | 链长了怎么不翻车 | 三表链、自连接、重复计数与外连接陷阱 |
拆是为了不重复,拼是为了能查询。范式决定怎么拆,JOIN 决定怎么拼——两件事是一枚硬币的正反面。
JOIN 把宽表拼出来了,但有些问题的答案"藏在另一个查询的结果里":比平均价高的书有哪些、买过 A 又买过 B 的顾客是谁。把一个查询的结果喂给另一个查询,就是第 6 章的子查询与集合运算。