一.多表查询的分类
1.角度1:等值连接 vs 非等值连接
非等值连接:进行多表查询时,两张表间不存在相同字段,此时使用非等值连接
例:SELECT e.last_name,e.salary,j.grade_level
FROM employees e,job_grades j
WHERE e.salary BETWEEN j.lowest_sal AND j.highest_sal;
2.角度2.自连接 vs 非自连接
自连接:同一张表内数据相互连接,可以看作两张相同的表间连接
例:#查询员工姓名、员工id及其管理者的姓名、id
SELECT emp.last_name, emp.employee_id, mag.last_name, mag.employee_id
FROM employees emp,employees mag
WHERE emp.manager_id = mag.employee_id;
非自连接:不同表内数据相互连接
3.角度3.内连接 vs 外连接
(1)内连接:合并具有同一列的两个以上的表的行,结果集 中不包含一个表与另一个表不匹配的行
例:SELECT employee_id,department_name
FROM employees e,departments
WHERE e.department_id = d.department_id;
(2)外连接:合并具有同一列的两个以上的表的行,结果集 中除了包含一个表与另一个表匹配的行之外,还包含左表 或 右表中不匹配的行。 还包含左表不匹配行——左外连接;还包含右表不匹配行——右外连接;左右表不匹配行都包含——满外连接;
SQL92语法实现内连接:同上内连接例子 ;(****但MySQL中不支持SQL92的写法)
SQL92语法实现外连接:使用 + ;(****但MySQL中不支持SQL92的写法)
例:SSELECT employee_id,department_name
FROM employees e,departments
WHERE e.department_id = d.department_id; #(+)写在少行的那一边
SQL99语法实现内连接:(INNER) JOIN...ON... #INNER可以不写
例:SELECT employee_id,department_name
FROM employees e JOIN departments d #JOIN用于连接两表
ON e.department_id = d,department_id; #ON用于条件匹配
例:若想实现多表查询
SELECT employee_id,department_name,location_id
FROM employees e
JOIN departments d
ON e.department_id = d,department_id
JOIN locations l
ON d.location_id = l.location_id; #每多连接一张表,加一个JOIN...ON...语句
SQL99语法实现外连接:OUTER JOIN...ON...
左外连接:LEFT (OUTER) JOIN...ON... #OUTER可不加
右外连接:RIGHT (OUTER) JOIN...ON...
满外连接:FULL (OUTER) JOIN..ON... #但MySQL不支持FULL OUTER JOIN...ON...的写法
二.使用SQL99实现7种JOIN操作
1.UNION语句:合并查询结果
利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组成单个结果集。合并时,两个表对应的列数和数据类型必须相同,并且相互对应。
各个SELECT语句之间使用UNION或UNION ALL关键字分隔。
UNION操作符返回两个查询的结果集的并集,并去除重复记录。
UNION ALL操作符返回两个查询的结果集的并集,对于两个结果集的重复部分,不去重。
#因为相比UNION ALL,UNION多了一步去重操作,效率变低,所以能用UNION ALL的情况下一般不用UNION
2.第一种:内连接:SELECT employee_id,department_name
FROM employees e JOIN departments d #JOIN用于连接两表
ON e.department_id = d,department_id; #ON用于条件匹配
3.第二种:左外连接:SELECT employee_id,department_name
FROM employees e LEFT (OUTER) JOIN departments d
ON e.department_id = d,department_id;
4.第三种:右外连接:SELECT employee_id,department_name
FROM employees e RIGHT (OUTER) JOIN departments d
ON e.department_id = d,department_id;
5.第四种:左外连接的基础上去掉所有的两表匹配行:
SELECT employee_id,department_name
FROM employees e LEFT (OUTER) JOIN departments d
ON e.department_id = d,department_id
WHERE d.department_id IS NULL;
6.第五种:右外连接的基础上去掉所有的两表匹配行:
SELECT employee_id,department_name
FROM employees e LEFT (OUTER) JOIN departments d
ON e.department_id = d,department_id
WHERE e.department_id IS NULL;
7.第六种:满外连接:第二种 UNION ALL 第五种:
SELECT employee_id,department_name
FROM employees e LEFT (OUTER) JOIN departments d
ON e.department_id = d,department_id
UNION ALL#两个结果集合并,不进行去重操作
SELECT employee_id,department_name
FROM employees e LEFT (OUTER) JOIN departments d
ON e.department_id = d,department_id
WHERE e.department_id IS NULL;
8.第七种:满外连接的基础上去掉所有的两表匹配行:第四种 UNION ALL 第五种
SELECT employee_id,department_name
FROM employees e LEFT (OUTER) JOIN departments d
ON e.department_id = d,department_id
WHERE d.department_id IS NULL
UNION ALL
SELECT employee_id,department_name
FROM employees e LEFT (OUTER) JOIN departments d
ON e.department_id = d,department_id
WHERE e.department_id IS NULL;