SELECT last_name, salary, grade_level FROM employees e, job_grades j WHERE e.salary BETWEEN j.lowest_sal AND j.highest_sal; +-------------+----------+-------------+ | last_name | salary | grade_level | +-------------+----------+-------------+ | King |24000.00| E | | Kochhar |17000.00| E | | De Haan |17000.00| E | | Hunold |9000.00| C | | Ernst |6000.00| C | | Austin |4800.00| B | | Pataballa |4800.00| B | | Lorentz |4200.00| B | | Greenberg |12000.00| D |
角度2 - 自连接 非自连接
自连接
同一个表的自我连接,对应表关系中的自我引用关系
1 2 3 4 5 6 7 8 9 10
SELECT emp.employee_id "员工ID", emp.last_name, mgr.employee_id "管理者ID", mgr.last_name FROM employees emp, employees mgr WHERE emp.manager_id = mgr.employee_id; +--------+-------------+----------+-----------+ | 员工ID | last_name | 管理者ID | last_name | +--------+-------------+----------+-----------+ |101| Kochhar |100| King | |102| De Haan |100| King | |103| Hunold |102| De Haan | |104| Ernst |103| Hunold |
非自连接
不是一个表的自我连接即为非自连接
角度3 - 内连接 外连接
内连接
合并具有同一列的两个以上的表的行,结果集不包含一个表与另一个表不匹配的行
外连接
外连接的分类:
左外连接:结果集中结果集中除了返回一个表与另一个表匹配的行,还返回左表不匹配的行
右外连接:结果集中结果集中除了返回一个表与另一个表匹配的行,还返回右表不匹配的行
满外连接:结果集中结果集中除了返回一个表与另一个表匹配的行,还返回左表或者右表不匹配的行
SQL92语法 —— MySQL不支持
1 2 3 4 5
# 查询所有的员工 SELECT e.employee_id, d.department_name FROM employees e, departments d # 因为有些员工没有部门,需要使用左外连接 WHere e.department_id = d.department_id(+);
SQL99语法实现外连接
左外连接LEFT [OUTER] JOHN
右外连接RIGHT [OUTER] JOHN
满外连接
FULL [OUTER] JOHN(MySQL不支持该语法)
1 2 3 4 5
# 查询所有的员工 SELECT e.employee_id, d.department_name FROM employees e LEFTOUTERJOIN departments d # 因为有些员工没有部门,需要使用左外连接 ON e.department_id = d.department_id;
7 种 JOHN 的实现
若有左、右两个表,分别对应两个集合A和B
A ∩ B - 内连接
1 2 3
SELECT employee_id, department_name FROM employees e JOIN departments d ON e.department_id = d.department_id
A ∪ (B非) - 左外连接
1 2 3
SELECT employee_id, department_name FROM employees e LEFTJOIN departments d ON e.department_id = d.department_id
B ∪ (A非) - 右外连接
1 2 3
SELECT employee_id, department_name FROM employees e RIGHTJOIN departments d ON e.department_id = d.department_id
A - B
A - B = A∪(B非) - A∩B = 左外连接 - 内连接
1 2 3 4
SELECT employee_id, department_name FROM employees e LEFTJOIN departments d ON e.department_id = d.department_id WHERE d.department_id ISNULL;
B - A
B - A = B∪(A非)- A∩B = 右外连接 - 内连接
1 2 3 4
SELECT employee_id, department_name FROM employees e RIGHTJOIN departments d ON e.department_id = d.department_id WHERE e.department_id ISNULL;
A ∪ B - 满外连接
A ∪ B = A∪(B非) + (B-A) = 左外连接 + (B-A)
1 2 3 4 5 6 7 8 9 10
# A∪(B非) 左外连接 SELECT employee_id, department_name FROM employees e LEFTJOIN departments d ON e.department_id = d.department_id UNIONALL # B-A SELECT employee_id, department_name FROM employees e RIGHTJOIN departments d ON e.department_id = d.department_id WHERE e.department_id ISNULL;
等价于
A ∪ B = B∪(A非) + (A-B) = 右外连接 + (A-B)
1 2 3 4 5 6 7 8 9 10
# B∪(A非) 右外连接 SELECT employee_id, department_name FROM employees e RIGHTJOIN departments d ON e.department_id = d.department_id UNIONALL # A-B SELECT employee_id, department_name FROM employees e LEFTJOIN departments d ON e.department_id = d.department_id WHERE d.department_id ISNULL;
(A-B) ∪ (B-A)
1 2 3 4 5 6 7 8 9 10 11
# A-B SELECT employee_id, department_name FROM employees e LEFTJOIN departments d ON e.department_id = d.department_id WHERE d.department_id ISNULL UNIONALL # B-A SELECT employee_id, department_name FROM employees e RIGHTJOIN departments d ON e.department_id = d.department_id WHERE e.department_id ISNULL;