多表查询,也称为关联查询,指两个或更多个表一起完成查询操作。
前提条件:这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段,这个
关联字段可能建立了外键,也可能没有建立外键。比如:员工表和部门表,这两个表依靠“部门编号”进
行关联
在 WHERE子句中写入连接条件
案例:查询员工的姓名及其部门名称
select e.last_name,d.department_name
from employees e,departments d
where e.`department_id`= d.`department_id`;
多表查询分类
等值连接VS非等值连接
等值连接
练习:查询员工的employee_id,last_name,department_name,city
SELECT e.employee_id,e.last_name,d.department_name,l.city,e.department_id,l.location_id
FROM employees e,departments d,locations l
WHERE e.`department_id`= d.`department_id`AND d.`location_id`= l.`location_id`;
非等值连接
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`;WHERE e.`salary`>= j.`lowest_sal`AND e.`salary`<= j.`highest_sal`;
自连接VS非自连接
自连接
自己连接自己
查询员工id,员工姓名及其管理者的id和姓名
SELECT emp.employee_id,emp.last_name,mgr.employee_id,mgr.last_name
FROM employees emp ,employees mgr
WHERE emp.`manager_id`= mgr.`employee_id`;
外连接
两张不同的表活两张以上
内连接VS外连接
内连接
**内连接: 合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行
通俗来讲就是取交集**SELECT employee_id,department_name
FROM employees e,departments d
WHERE e.`department_id`= d.department_id;#只有106条记录
#左外连接SELECT last_name,department_name
FROM employees ,departments
WHERE employees.department_id = departments.department_id(+);#右外连接SELECT last_name,department_name
FROM employees ,departments
WHERE employees.department_id(+)= departments.department_id;
SQL99语法实现多表查询(mysql不支持SQL92的外连接)
基本语法
使用join...on子句创建连接的语法结构
SELECT table1.column, table2.column,table3.columnFROM table1
JOIN table2 ON table1 和 table2 的连接条件
JOIN table3 ON table2 和 table3 的连接条件
它的嵌套逻辑类似我们使用的 FOR 循环:
for t1 in table1:
for t2 in table2:
if condition1:
for t3 in table3:
if condition2:
output t1 + t2 + t3
语法说明:
可以使用 ON 子句指定额外的连接条件。
这个连接条件是与其它条件分开的。
ON 子句使语句具有更高的易读性。
关键字 JOIN、INNERJOIN、CROSSJOIN 的含义是一样的,都表示内连接
内连接(inner join)的实现
SELECT 字段列表
FROM A表 INNERJOIN B表
ON 关联条件
WHERE 等其他子句;INNER 可以省略
SELECT last_name,department_name,city
FROM employees e JOIN departments d
ON e.`department_id`= d.`department_id`JOIN locations l
ON d.`location_id`= l.`location_id`;
外连接(outer join)的实现
左外连接(LEFT OUTER JOIN)
SELECT 字段列表
FROM A表 LEFTJOIN B表
ON 关联条件
WHERE 等其他子句;
查询所有的员工的last_name,department_name信息
# 左外连接:SELECT last_name,department_name
FROM employees e LEFTJOIN departments d
ON e.`department_id`= d.`department_id`;#右外连接:SELECT last_name,department_name
FROM employees e RIGHTOUTERJOIN departments d
ON e.`department_id`= d.`department_id`;OUTER 可以省略
合并查询结果 利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组合成单个结果集。合并
时,两个表对应的列数和数据类型必须相同,并且相互对应。各个SELECT语句之间使用UNION或UNIONALL关键字分隔。
UNION 操作符返回两个查询的结果集的并集,去除重复记录。
UNIONALL操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。
执行UNIONALL语句时所需要的资源比UNION语句少。如果明确知道合并数据后的结果数据
不存在重复数据,或者不需要去除重复的数据,则尽量使用UNIONALL语句,以提高数据查询的效
率
查询部门编号>90或邮箱包含a的员工信息
#方式1SELECT*FROM employees WHERE email LIKE'%a%'OR department_id>90;#方式2SELECT*FROM employees WHERE email LIKE'%a%'UNIONSELECT*FROM employees WHERE department_id>90;
7种SQL JOINS的实现(!)
代码实现
中图:内连接
SELECT e.employee_id,d.department_name
FROM employees e JOIN departments d
ON e.`department_id`= d.`department_id`;
左上图:左外连接
SELECT e.employee_id,d.department_name
FROM employees e LEFTJOIN departments d
ON e.`department_id`= d.`department_id`;
右上图:右外连接
SELECT employee_id,department_name
FROM employees e RIGHTJOIN departments d
ON e.`department_id`= d.`department_id`;
左中图:
SELECT employee_id,department_name
FROM employees e LEFTJOIN departments d
ON e.`department_id`= d.`department_id`WHERE d.`department_id`ISNULL;
右中图:
SELECT employee_id,department_name
FROM employees e RIGHTJOIN departments d
ON e.`department_id`= d.`department_id`WHERE e.`department_id`ISNULL;
左下图:满外连接
方式1:左上图 UNIONALL 右中图
SELECT employee_id,department_name
FROM employees e LEFTJOIN departments d
ON e.`department_id`= d.`department_id`UNIONALLSELECT employee_id,department_name
FROM employees e RIGHTJOIN departments d
ON e.`department_id`= d.`department_id`WHERE e.`department_id`ISNULL;
方式2:左中图 UNIONALL 右上图
SELECT employee_id,department_name
FROM employees e LEFTJOIN departments d
ON e.`department_id`= d.`department_id`WHERE d.`department_id`ISNULLUNIONALLSELECT employee_id,department_name
FROM employees e RIGHTJOIN departments d
ON e.`department_id`= d.`department_id`;
右下图:左中图 UNIONALL 右中图
SELECT employee_id,department_name
FROM employees e LEFTJOIN departments d
ON e.`department_id`= d.`department_id`WHERE d.`department_id`ISNULLUNIONALLSELECT employee_id,department_name
FROM employees e RIGHTJOIN departments d
ON e.`department_id`= d.`department_id`WHERE e.`department_id`ISNULL;
SQL99语法新特性
自然连接(natural join)
可以把自然连接理解为 SQL92 中的等值连接。它会帮你自动查询两张连接表中 所有相同的字段 ,然后进行
等值连接
在SQL92标准中:
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id`= d.`department_id`AND e.`manager_id`= d.`manager_id`;
在 SQL99 中你可以写成:
SELECT employee_id,last_name,department_name
FROM employees e NATURALJOIN departments d;
using连接
当我们进行连接的时候,SQL99还支持使用 USING 指定数据表里的 同名字段 进行等值连接。但是只能配
合JOIN一起使用。比如:
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
USING(department_id);
你能看出与自然连接 NATURALJOIN 不同的是,USING 指定了具体的相同的字段名称,你需要在 USING
的括号 () 中填入要指定的同名字段。同时使用 JOIN...USING 可以简化 JOINON 的等值连接。它与下
面的 SQL 查询结果是相同的:
SELECT employee_id,last_name,department_name
FROM employees e ,departments d
WHERE e.department_id = d.department_id;
select e.last_name,e.department_id,d.department_name
from employees e
leftjoin departments d
on e.`department_id`= d.`department_id`;
2.查询90号部门员工的job_id和90号部门的location_id
select e.job_id,d.location_id
from employees e join departments d
on e.`department_id`= d.`department_id`and e.`department_id`=90;
或
SELECT job_id, location_id
FROM employees e, departments d
WHERE e.`department_id`= d.`department_id`AND e.`department_id`=90;
或
SELECT job_id, location_id
FROM employees e
JOIN departments d
ON e.`department_id`= d.`department_id`WHERE e.`department_id`=90;
SELECT e.last_name,d.department_name,d.location_id,l.city
FROM employees e JOIN departments d
ON e.`department_id`= d.`department_id`LEFTJOIN locations l
ON d.`location_id`= l.`location_id`WHERE commission_pct ISNOTNULL
SELECT last_name , job_id , e.department_id , department_name
FROM employees e, departments d, locations l
WHERE e.`department_id`= d.`department_id`AND d.`location_id`= l.`location_id`AND city ='Toronto';
或
SELECT last_name , job_id , e.department_id , department_name
FROM employees e
JOIN departments d
ON e.`department_id`= d.`department_id`JOIN locations l
ON l.`location_id`= d.`location_id`WHERE l.`city`='Toronto';
SELECT department_name, street_address, last_name, job_id, salary
FROM employees e JOIN departments d
ON e.department_id = d.department_id
JOIN locations l
ON d.`location_id`= l.`location_id`WHERE department_name ='Executive'
方式1:
SELECT d.department_id
FROM departments d LEFTJOIN employees e
ON e.department_id = d.`department_id`WHERE e.department_id ISNULL
或
方式2:
SELECT department_id
FROM departments d
WHERENOTEXISTS(SELECT*FROM employees e
WHERE e.`department_id`= d.`department_id`)
8.查询哪个城市没有部门
SELECT l.location_id,l.city
FROM locations l LEFTJOIN departments d
ON l.`location_id`= d.`location_id`WHERE d.`location_id`ISNULL
9. 查询部门名为 Sales 或 IT 的员工信息
SELECT employee_id,last_name,department_name
FROM employees e,departments d
WHERE e.department_id = d.`department_id`AND d.`department_name`IN('Sales','IT');