MySQL(33)如何进行多表联合查询?

775 阅读4分钟

多表联合查询(Join)是SQL中一种用来在多个表之间建立关联并获取相关数据的操作。常见的联合查询类型包括内连接(INNER JOIN)、左连接(LEFT JOIN)、右连接(RIGHT JOIN)和全连接(FULL JOIN)。下面详细介绍每种联合查询的使用方法,并结合代码示例。

示例数据库和表结构

假设我们有一个公司数据库,其中有两个表:employeesdepartments

-- 创建数据库
CREATE DATABASE company;

-- 选择数据库
USE company;

-- 创建表 departments
CREATE TABLE departments (
    dept_id INT AUTO_INCREMENT PRIMARY KEY,
    dept_name VARCHAR(100) NOT NULL
);

-- 创建表 employees
CREATE TABLE employees (
    emp_id INT AUTO_INCREMENT PRIMARY KEY,
    emp_name VARCHAR(100) NOT NULL,
    emp_position VARCHAR(100),
    emp_salary DECIMAL(10, 2),
    hire_date DATE,
    dept_id INT,
    FOREIGN KEY (dept_id) REFERENCES departments(dept_id)
);

-- 插入示例数据到 departments 表
INSERT INTO departments (dept_name)
VALUES 
('HR'),
('Engineering'),
('Marketing');

-- 插入示例数据到 employees 表
INSERT INTO employees (emp_name, emp_position, emp_salary, hire_date, dept_id)
VALUES 
('John Doe', 'Manager', 75000.00, '2023-10-01', 1),
('Jane Smith', 'Developer', 60000.00, '2023-09-01', 2),
('Alice Johnson', 'Analyst', 50000.00, '2023-08-01', 1),
('Bob Brown', 'Developer', 70000.00, '2023-07-01', 2),
('Charlie Brown', 'Tester', 55000.00, '2023-11-01', 3),
('Emma White', 'Developer', 60000.00, '2023-08-20', 2);

1. 内连接(INNER JOIN)

INNER JOIN 返回两个表中满足连接条件的记录。

示例:获取每个员工及其所在部门的名称

SELECT employees.emp_name, employees.emp_position, departments.dept_name
FROM employees
INNER JOIN departments ON employees.dept_id = departments.dept_id;

结果:

emp_name      | emp_position | dept_name
--------------|--------------|-----------
John Doe      | Manager      | HR
Jane Smith    | Developer    | Engineering
Alice Johnson | Analyst      | HR
Bob Brown     | Developer    | Engineering
Charlie Brown | Tester       | Marketing
Emma White    | Developer    | Engineering

2. 左连接(LEFT JOIN)

LEFT JOIN 返回左表中的所有记录,以及右表中满足连接条件的记录。不满足条件的右表记录将显示为 NULL

示例:获取每个员工及其所在部门的名称(包括没有部门的员工)

假设我们插入一个没有部门的员工:

INSERT INTO employees (emp_name, emp_position, emp_salary, hire_date)
VALUES ('Mark Twain', 'Consultant', 80000.00, '2023-12-01');

然后执行左连接查询:

SELECT employees.emp_name, employees.emp_position, departments.dept_name
FROM employees
LEFT JOIN departments ON employees.dept_id = departments.dept_id;

结果:

emp_name      | emp_position | dept_name
--------------|--------------|-----------
John Doe      | Manager      | HR
Jane Smith    | Developer    | Engineering
Alice Johnson | Analyst      | HR
Bob Brown     | Developer    | Engineering
Charlie Brown | Tester       | Marketing
Emma White    | Developer    | Engineering
Mark Twain    | Consultant   | NULL

3. 右连接(RIGHT JOIN)

RIGHT JOIN 返回右表中的所有记录,以及左表中满足连接条件的记录。不满足条件的左表记录将显示为 NULL

示例:获取每个员工及其所在部门的名称(包括没有员工的部门)

SELECT employees.emp_name, employees.emp_position, departments.dept_name
FROM employees
RIGHT JOIN departments ON employees.dept_id = departments.dept_id;

结果:

emp_name      | emp_position | dept_name
--------------|--------------|-----------
John Doe      | Manager      | HR
Alice Johnson | Analyst      | HR
Jane Smith    | Developer    | Engineering
Bob Brown     | Developer    | Engineering
Emma White    | Developer    | Engineering
Charlie Brown | Tester       | Marketing
NULL          | NULL         | HR

4. 全连接(FULL JOIN)

FULL JOIN 返回两个表中的所有记录,只要在其中至少有一个表中有匹配。MySQL 不直接支持 FULL JOIN,但可以通过使用 UNION 来实现。

示例:获取所有员工及其所在部门的名称(包括没有部门的员工和没有员工的部门)

SELECT employees.emp_name, employees.emp_position, departments.dept_name
FROM employees
LEFT JOIN departments ON employees.dept_id = departments.dept_id
UNION
SELECT employees.emp_name, employees.emp_position, departments.dept_name
FROM employees
RIGHT JOIN departments ON employees.dept_id = departments.dept_id;

结果:

emp_name      | emp_position | dept_name
--------------|--------------|-----------
John Doe      | Manager      | HR
Alice Johnson | Analyst      | HR
Jane Smith    | Developer    | Engineering
Bob Brown     | Developer    | Engineering
Emma White    | Developer    | Engineering
Charlie Brown | Tester       | Marketing
Mark Twain    | Consultant   | NULL
NULL          | NULL         | HR

5. 交叉连接(CROSS JOIN)

CROSS JOIN 返回两个表的笛卡尔积,即所有可能的组合。

示例:获取所有员工与所有部门的组合

SELECT employees.emp_name, departments.dept_name
FROM employees
CROSS JOIN departments;

结果:

emp_name      | dept_name
--------------|-----------
John Doe      | HR
John Doe      | Engineering
John Doe      | Marketing
Jane Smith    | HR
Jane Smith    | Engineering
Jane Smith    | Marketing
Alice Johnson | HR
Alice Johnson | Engineering
Alice Johnson | Marketing
Bob Brown     | HR
Bob Brown     | Engineering
Bob Brown     | Marketing
Charlie Brown | HR
Charlie Brown | Engineering
Charlie Brown | Marketing
Emma White    | HR
Emma White    | Engineering
Emma White    | Marketing
Mark Twain    | HR
Mark Twain    | Engineering
Mark Twain    | Marketing

6. 自连接(SELF JOIN)

自连接是表与其自身进行连接。

示例:获取每个员工及其直属上司的姓名

假设 employees 表中有一个 manager_id 列表示员工的直属上司:

-- 添加 manager_id 列
ALTER TABLE employees ADD manager_id INT;

-- 更新 manager_id 值
UPDATE employees SET manager_id = 1 WHERE emp_id = 2 OR emp_id = 4 OR emp_id = 6;
UPDATE employees SET manager_id = 2 WHERE emp_id = 3;
UPDATE employees SET manager_id = NULL WHERE emp_id = 1;

然后执行自连接查询:

SELECT e1.emp_name AS employee, e2.emp_name AS manager
FROM employees e1
LEFT JOIN employees e2 ON e1.manager_id = e2.emp_id;

结果:

employee      | manager
--------------|--------
John Doe      | NULL
Jane Smith    | John Doe
Alice Johnson | Jane Smith
Bob Brown     | John Doe
Charlie Brown | NULL
Emma White    | John Doe
Mark Twain    | NULL

小结

多表联合查询是SQL中非常强大的工具,它允许您在多个表之间建立关联并获取相关数据。通过使用 INNER JOINLEFT JOINRIGHT JOINFULL JOINCROSS JOIN 和自连接,您可以实现各种复杂的数据查询和分析。上述示例展示了如何在不同情况下使用这些联合查询,以实现多表数据的关联和提取。