假设有以下三张表:
-- 学生表
CREATE TABLE student (
student_id INT PRIMARY KEY,
name VARCHAR(100)
);
-- 课程表
CREATE TABLE course (
course_id INT PRIMARY KEY,
course_name VARCHAR(100),
teacher_id INT
);
-- 教师表
CREATE TABLE teacher (
teacher_id INT PRIMARY KEY,
teacher_name VARCHAR(100)
);
查询需求: 列出每个学生选的课程及任课教师姓名。
通常还需要一个中间表(选课表):
-- 选课表
CREATE TABLE enrollment (
enroll_id INT PRIMARY KEY,
student_id INT,
course_id INT
);
SELECT
student.name AS student_name,
course.course_name,
teacher.teacher_name
FROM enrollment
INNER JOIN student ON enrollment.student_id = student.student_id
INNER JOIN course ON enrollment.course_id = course.course_id
INNER JOIN teacher ON course.teacher_id = teacher.teacher_id;
enrollment
表把学生和课程联系起来。course
表中的teacher_id
字段进一步连接到教师表。假设有一张员工表:
-- 员工表
CREATE TABLE employee (
emp_id INT PRIMARY KEY,
emp_name VARCHAR(100),
manager_id INT -- 上级经理ID,指向本表emp_id
);
插入示例数据:
INSERT INTO employee (emp_id, emp_name, manager_id) VALUES
(1, '王总', NULL),
(2, '李经理', 1),
(3, '张主管', 2),
(4, '赵员工', 3);
查询每位员工及其经理的名字:
SELECT
e1.emp_name AS employee_name,
e2.emp_name AS manager_name
FROM employee e1
LEFT JOIN employee e2 ON e1.manager_id = e2.emp_id;
e1
表示员工自己。e2
表示经理。LEFT JOIN
,即使有些员工(如总经理)没有上级,结果中也能出现。ON
条件,或者写错了连接条件,就会出现笛卡尔积 现象,导致数据量暴涨。SELECT *
FROM 表A
CROSS JOIN 表B;
或
SELECT *
FROM 表A, 表B;
-- 员工表
CREATE TABLE employee (
emp_id INT PRIMARY KEY,
emp_name VARCHAR(100),
dept_id INT,
manager_id INT
);
-- 部门表
CREATE TABLE department (
dept_id INT PRIMARY KEY,
dept_name VARCHAR(100)
);
-- 经理表(也是员工,只是额外列出)
CREATE TABLE manager (
manager_id INT PRIMARY KEY,
manager_name VARCHAR(100)
);
-- 员工
INSERT INTO employee (emp_id, emp_name, dept_id, manager_id) VALUES
(1, '张三', 10, 100),
(2, '李四', 20, 101),
(3, '王五', 10, 100);
-- 部门
INSERT INTO department (dept_id, dept_name) VALUES
(10, '技术部'),
(20, '市场部');
-- 经理
INSERT INTO manager (manager_id, manager_name) VALUES
(100, '赵总'),
(101, '钱总');
SELECT
e.emp_name,
d.dept_name,
m.manager_name
FROM employee e
INNER JOIN department d ON e.dept_id = d.dept_id
INNER JOIN manager m ON e.manager_id = m.manager_id;
如果不用经理表,只用员工表(员工自己记录经理ID):
SELECT
e1.emp_name AS employee,
e2.emp_name AS manager
FROM employee e1
LEFT JOIN employee e2 ON e1.manager_id = e2.emp_id;
内容 | 关键词 | 说明 |
---|---|---|
多表联合查询 | 多次 INNER JOIN | 查询多张表的数据关联 |
自连接 | SELF JOIN | 表与自己连接,处理层级关系 |
笛卡尔积 | CROSS JOIN | 所有组合,通常需要避免 |