MySQL连接查询

掌握多表连接查询的使用方法

连接查询概述

连接查询用于从多个表中检索相关数据。通过连接条件,可以将不同表中的记录关联起来。

连接类型

  • 内连接(INNER JOIN) - 返回两个表中匹配的记录
  • 左连接(LEFT JOIN) - 返回左表所有记录和右表匹配的记录
  • 右连接(RIGHT JOIN) - 返回右表所有记录和左表匹配的记录
  • 全连接(FULL JOIN) - 返回两个表中所有记录
  • 交叉连接(CROSS JOIN) - 返回两个表的笛卡尔积
  • 自连接(SELF JOIN) - 表与自身连接

内连接(INNER JOIN)

内连接返回两个表中满足连接条件的记录,即两个表中都存在的记录。

内连接语法

SQL语法
SELECT 列名
FROM 表1
INNER JOIN 表2 ON 表1.列 = 表2.列;

内连接示例

SQL示例
-- 查询员工及其部门信息
SELECT e.name, d.department_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;

-- 查询订单及客户信息
SELECT o.order_id, c.customer_name, o.order_date
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id;
注意:INNER JOIN是默认的连接类型,可以简写为JOIN。

左连接(LEFT JOIN)

左连接返回左表的所有记录和右表中匹配的记录。如果右表中没有匹配的记录,则返回NULL值。

左连接语法

SQL语法
SELECT 列名
FROM 表1
LEFT JOIN 表2 ON 表1.列 = 表2.列;

左连接示例

SQL示例
-- 查询所有员工及其部门信息(包括没有部门的员工)
SELECT e.name, d.department_name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;

-- 查询所有客户及其订单信息(包括没有订单的客户)
SELECT c.customer_name, o.order_id, o.order_date
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id;

右连接(RIGHT JOIN)

右连接返回右表的所有记录和左表中匹配的记录。如果左表中没有匹配的记录,则返回NULL值。

右连接语法

SQL语法
SELECT 列名
FROM 表1
RIGHT JOIN 表2 ON 表1.列 = 表2.列;

右连接示例

SQL示例
-- 查询所有部门及其员工信息(包括没有员工的部门)
SELECT d.department_name, e.name
FROM employees e
RIGHT JOIN departments d ON e.department_id = d.id;

-- 查询所有产品及其订单信息(包括没有订单的产品)
SELECT p.product_name, o.order_id
FROM orders o
RIGHT JOIN products p ON o.product_id = p.product_id;
提示:在大多数情况下,LEFT JOIN和RIGHT JOIN可以互换使用,取决于哪个表作为主表。

全连接(FULL JOIN)

全连接返回两个表中所有记录。如果某一边没有匹配的记录,则返回NULL值。

注意:MySQL不支持FULL JOIN语法,但可以通过UNION LEFT JOIN和RIGHT JOIN来实现。

全连接实现方法

SQL示例
-- 使用UNION实现全连接
SELECT e.name, d.department_name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id
UNION
SELECT e.name, d.department_name
FROM employees e
RIGHT JOIN departments d ON e.department_id = d.id;

交叉连接(CROSS JOIN)

交叉连接返回两个表的笛卡尔积,即左表的每一行与右表的每一行组合。

交叉连接语法

SQL语法
SELECT 列名
FROM 表1
CROSS JOIN 表2;

交叉连接示例

SQL示例
-- 生成所有可能的颜色和尺寸组合
SELECT c.color_name, s.size_name
FROM colors c
CROSS JOIN sizes s;
注意:交叉连接会产生大量结果,应谨慎使用,特别是在大表上。

自连接(SELF JOIN)

自连接是指表与自身连接,常用于查询具有层次结构的数据。

自连接示例

SQL示例
-- 查询员工及其经理信息
SELECT e1.name AS employee_name, e2.name AS manager_name
FROM employees e1
LEFT JOIN employees e2 ON e1.manager_id = e2.employee_id;

多表连接

可以连接两个以上的表,只需在查询中添加更多的JOIN子句。

多表连接示例

SQL示例
-- 查询订单详情,包括客户和产品信息
SELECT o.order_id, c.customer_name, p.product_name, oi.quantity
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id
INNER JOIN order_items oi ON o.order_id = oi.order_id
INNER JOIN products p ON oi.product_id = p.product_id;

连接性能优化

为了提高连接查询的性能,可以考虑以下优化策略:

  • 在连接条件列上创建索引
  • 只选择需要的列,避免使用SELECT *
  • 使用合适的连接类型
  • 避免在大型表上进行交叉连接

连接查询中的NULL值处理

在连接查询中,NULL值可能会导致意外的结果。需要特别注意:

使用COALESCE处理NULL值

SQL示例
-- 使用COALESCE为NULL值提供默认值
SELECT e.name, COALESCE(d.department_name, '未分配部门') AS department
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;

使用IFNULL处理NULL值

SQL示例
-- 使用IFNULL为NULL值提供默认值
SELECT e.name, IFNULL(d.department_name, '未分配部门') AS department
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;

连接查询中的聚合函数

可以在连接查询中使用聚合函数,对连接后的结果进行统计:

使用GROUP BY和聚合函数

SQL示例
-- 统计每个部门的员工数量
SELECT d.department_name, COUNT(e.id) AS employee_count
FROM departments d
LEFT JOIN employees e ON d.id = e.department_id
GROUP BY d.department_name;

连接查询中的条件过滤

可以在连接查询中使用WHERE子句对结果进行过滤:

WHERE子句的位置

SQL示例
-- 查询特定部门的员工信息
SELECT e.name, d.department_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id
WHERE d.department_name = '技术部';

连接查询中的排序

可以使用ORDER BY子句对连接查询的结果进行排序:

ORDER BY子句的使用

SQL示例
-- 按部门名称和员工姓名排序
SELECT e.name, d.department_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id
ORDER BY d.department_name, e.name;

连接查询中的表别名

使用表别名可以简化SQL语句,提高可读性:

表别名的使用

SQL示例
-- 使用表别名简化查询
SELECT e.name, d.department_name
FROM employees AS e
INNER JOIN departments AS d ON e.department_id = d.id;

连接查询中的复杂条件

可以在连接条件中使用多个条件:

多条件连接

SQL示例
-- 使用多个连接条件
SELECT e.name, p.project_name
FROM employees e
INNER JOIN employee_projects ep ON e.id = ep.employee_id AND ep.is_active = 1
INNER JOIN projects p ON ep.project_id = p.id;

下一步学习

掌握了连接查询后,您可以继续学习: