SQL多表连结完全教程
掌握INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL OUTER JOIN等连结方式
SQL连结简介
SQL JOIN用于根据两个或多个表之间的相关列合并它们的数据。通过连结,我们可以从多个表中检索相关数据。
示例表结构
Employees
emp_id (PK)
name
dept_id (FK)
Departments
dept_id (PK)
dept_name
INNER JOIN(内连结)
返回两个表中匹配的记录。
SELECT e.emp_id, e.name, d.dept_name
FROM Employees e
INNER JOIN Departments d ON e.dept_id = d.dept_id;
FROM Employees e
INNER JOIN Departments d ON e.dept_id = d.dept_id;
💡 注意: INNER JOIN只返回两个表中都有匹配的记录。
LEFT JOIN(左外连结)
返回左表的所有记录和右表中匹配的记录。
SELECT e.emp_id, e.name, d.dept_name
FROM Employees e
LEFT JOIN Departments d ON e.dept_id = d.dept_id;
FROM Employees e
LEFT JOIN Departments d ON e.dept_id = d.dept_id;
A
左表 (Employees)
B
右表 (Departments)
RIGHT JOIN(右外连结)
返回右表的所有记录和左表中匹配的记录。
SELECT e.emp_id, e.name, d.dept_name
FROM Employees e
RIGHT JOIN Departments d ON e.dept_id = d.dept_id;
FROM Employees e
RIGHT JOIN Departments d ON e.dept_id = d.dept_id;
FULL OUTER JOIN(全外连结)
返回两个表的所有记录。
-- SQL Server, PostgreSQL等
SELECT e.emp_id, e.name, d.dept_name
FROM Employees e
FULL OUTER JOIN Departments d ON e.dept_id = d.dept_id;
-- MySQL替代方案(不支持FULL JOIN)
SELECT e.emp_id, e.name, d.dept_name
FROM Employees e LEFT JOIN Departments d ON e.dept_id = d.dept_id
UNION
SELECT e.emp_id, e.name, d.dept_name
FROM Employees e RIGHT JOIN Departments d ON e.dept_id = d.dept_id;
SELECT e.emp_id, e.name, d.dept_name
FROM Employees e
FULL OUTER JOIN Departments d ON e.dept_id = d.dept_id;
-- MySQL替代方案(不支持FULL JOIN)
SELECT e.emp_id, e.name, d.dept_name
FROM Employees e LEFT JOIN Departments d ON e.dept_id = d.dept_id
UNION
SELECT e.emp_id, e.name, d.dept_name
FROM Employees e RIGHT JOIN Departments d ON e.dept_id = d.dept_id;
CROSS JOIN(交叉连结)
返回两个表的笛卡尔积(所有可能的组合)。
SELECT e.name, d.dept_name
FROM Employees e
CROSS JOIN Departments d;
FROM Employees e
CROSS JOIN Departments d;
⚠️ 警告: CROSS JOIN可能产生大量结果,使用时需谨慎。
综合示例
三表连结示例
SELECT
o.order_id,
c.customer_name,
p.product_name,
od.quantity,
o.order_date
FROM Orders o
INNER JOIN Customers c ON o.customer_id = c.customer_id
INNER JOIN OrderDetails od ON o.order_id = od.order_id
INNER JOIN Products p ON od.product_id = p.product_id
WHERE o.order_date >= '2023-01-01'
ORDER BY o.order_date DESC;
o.order_id,
c.customer_name,
p.product_name,
od.quantity,
o.order_date
FROM Orders o
INNER JOIN Customers c ON o.customer_id = c.customer_id
INNER JOIN OrderDetails od ON o.order_id = od.order_id
INNER JOIN Products p ON od.product_id = p.product_id
WHERE o.order_date >= '2023-01-01'
ORDER BY o.order_date DESC;
使用表别名
SELECT
e.emp_id,
e.name AS employee_name,
d.dept_name,
m.name AS manager_name
FROM Employees e
LEFT JOIN Departments d ON e.dept_id = d.dept_id
LEFT JOIN Employees m ON e.manager_id = m.emp_id;
e.emp_id,
e.name AS employee_name,
d.dept_name,
m.name AS manager_name
FROM Employees e
LEFT JOIN Departments d ON e.dept_id = d.dept_id
LEFT JOIN Employees m ON e.manager_id = m.emp_id;
快速参考
INNER JOIN - 匹配的记录
LEFT JOIN - 左表全部 + 右表匹配
RIGHT JOIN - 右表全部 + 左表匹配
FULL JOIN - 两个表全部记录
CROSS JOIN - 笛卡尔积
LEFT JOIN - 左表全部 + 右表匹配
RIGHT JOIN - 右表全部 + 左表匹配
FULL JOIN - 两个表全部记录
CROSS JOIN - 笛卡尔积
最佳实践
- ✅ 使用表别名提高可读性
- ✅ 为连结列创建索引
- ✅ 明确指定连结条件
- ✅ 使用WHERE子句过滤结果
- ✅ 测试查询性能
常见问题
Q: INNER JOIN和LEFT JOIN有什么区别?
A: INNER JOIN只返回匹配的记录,LEFT JOIN返回左表所有记录和右表匹配的记录。
Q: 为什么我的查询返回太多记录?
A: 可能是缺少连结条件或使用了CROSS JOIN。
Q: 如何优化多表连结查询?
A: 使用索引、减少返回列数、尽早过滤数据。