SQL 联结(JOIN)详解

什么是联结?

在关系型数据库中,为了减少数据冗余、提高存储效率,通常会将数据分散存储在多个表中。联结(JOIN) 是一种机制,用于在一条 SELECT 语句中从多个表检索数据,通过表之间的关联字段将数据组合起来。


为什么使用联结?

  • 避免数据重复:每个数据只在一个表中存储一次,节省空间,避免更新异常。

  • 易于维护:修改某个数据时,只需更新一张表,相关表无需改动。

  • 增强可伸缩性:能够适应数据量的增长和复杂查询的需求。


笛卡尔积与 WHERE 子句

当联结两个表且没有指定联结条件时,会返回笛卡尔积,第一个表的每一行与第二个表的每一行配对,结果行数为两表行数乘积。例如:

SELECT * FROM 表1, 表2;   -- 无 WHERE 条件

通常这不是我们想要的。因此,必须使用 WHERE 子句指定联结条件,过滤出匹配的行。


联结的类型

内联结(INNER JOIN)

返回两个表中满足联结条件的行。是最常用的联结类型。

-- 使用 INNER JOIN 语法
SELECT *
FROM Vendors
INNER JOIN Products ON Vendors.vend_id = Products.vend_id;

-- 等价于隐式内联结(逗号 + WHERE)
SELECT *
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;

自联结(SELF JOIN)

将同一个表视为两个不同的表进行联结,常用于替代子查询。

示例:查找与 Jim Jones 同一公司的客户。

SELECT c1.cust_id, c1.cust_name, c1.cust_contact
FROM Customers c1
INNER JOIN Customers c2 ON c1.cust_name = c2.cust_name
WHERE c2.cust_contact = 'Jim Jones';

自然联结(NATURAL JOIN)

自然联结会自动排除重复的列,使每一列只出现一次。多数 DBMS 会自动完成,但实际使用中常显式指定列以避免歧义。

SELECT C.*, O.order_num, O.order_date
FROM Customers C
INNER JOIN Orders O ON C.cust_id = O.cust_id
INNER JOIN OrderItems OI ON O.order_num = OI.order_num
WHERE OI.prod_id = 'RGAN01';

外联结(OUTER JOIN)

不仅返回匹配的行,还返回左表或右表中不匹配的行。

  • LEFT OUTER JOIN:返回左表所有行,右表无匹配则用 NULL 填充。
  • RIGHT OUTER JOIN:返回右表所有行,左表无匹配则用 NULL 填充。
  • FULL OUTER JOIN:返回左右表所有行,无匹配则填充 NULL(部分 DBMS 支持)。
-- 左外联结:返回所有客户及其订单号(即使没有订单)
SELECT Customers.cust_id, Orders.order_num
FROM Customers
LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id;

叉联结(CROSS JOIN)

有时,返回笛卡尔积,即两个表的每一行相互组合。很少直接使用。

SELECT * FROM Vendors CROSS JOIN Products;

img


联结多个表

SQL 不限制联结的表数,但联结越多,性能开销越大。

SELECT *
FROM OrderItems, Products, Vendors
WHERE Products.vend_id = Vendors.vend_id
  AND OrderItems.prod_id = Products.prod_id
  AND order_num = 20007;

联结与聚集函数

聚集函数(如 COUNTSUM)可与联结结合使用,进行分组统计。

示例:统计每个客户的订单数。

SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord
FROM Customers
LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id
GROUP BY Customers.cust_id;

性能注意事项

  • 联结操作会消耗数据库资源,表越多、数据量越大,性能下降越明显。
  • 尽量避免不必要的联结。
  • 确保联结条件正确,否则可能返回笛卡尔积或错误数据。
  • 测试复杂联结时,可先分别验证每个子查询的正确性。

联结语法总结

联结类型 关键字 说明
内联结 INNER JOIN, + WHERE 仅返回匹配的行
左外联结 LEFT OUTER JOIN 返回左表所有行,右表无匹配补 NULL
右外联结 RIGHT OUTER JOIN 返回右表所有行,左表无匹配补 NULL
全外联结 FULL OUTER JOIN 返回所有行,无匹配补 NULL
自联结 同一表用不同别名联结 用于同一张表内的关联查询
自然联结 NATURAL JOIN 自动按同名列联结(不常用)
叉联结 CROSS JOIN 返回笛卡尔积

注意:不同数据库对联结语法的支持略有差异,请参考相应文档。

posted @ 2022-11-21 10:50  克峰同学  阅读(57)  评论(0)    收藏  举报