一、连接查询-SQL99标准
1、分类
(1)内连接:inner join
(2)外连接:
① 左外连接:left 【outer】
② 右外连接:right 【outer】
③ 全外连接:full 【outer】
(3)交叉连接:cross
2、语法格式
select 查询列表
from 表1 别名 【连接类型】
join 表2 别名
on 连接条件
【where 筛选条件】
【group by 分组】
【having 筛选条件】
【order by 排序列表】
3、
二、SQL99 标准
1、内连接
(1)分类
等值连接
非等值连接
自连接
(2)语法格式
select 查询列表
from 表1 别名
【inner】 join 表2 别名 on 连接条件
where 筛选条件
group by 分组列表
having 分组后的筛选
order by 排序列表
limit 子句;
(3)特点
①表的顺序可以调换,可以添加排序、分组、筛选;
②内连接的结果=多表的交集,inner join 和 SQL92 语法中的等值连接效果是一样的,都是查询多表的交集;
③n表连接至少需要n-1个连接条件;
④ inner 可以省略,筛选条件放在 where 后面,连接条件放在 on 语句后面,提高分离性,便于阅读;
2、外连接
(1)分类
左外连接
右外连接
全外连接
(2)语法格式
select 查询列表
from 表1 别名
left|right|full【outer】 join 表2 别名 on 连接条件
where 筛选条件
group by 分组列表
having 分组后的筛选
order by 排序列表
limit 子句;
(3)特点
①查询的结果=主表中所有的行,如果从表和它匹配的将显示匹配行,如果从表没有匹配的则显示null
②left join 左边的就是主表,right join 右边的就是主表full join 两边都是主表
③一般用于查询除了交集部分的剩余的不匹配的行;
④ 外连接的查询结果为主表中的所有记录,如果从表中有和它匹配的,则显示匹配的值,如果从表中没有和它匹配的,则显示 null;
⑤ 外连接查询结果 = 内连接结果 + 主表中有而从表没有的记录;
⑥ 全外连接 = 内连接结果 + 表1中有但表2中没有的 + 表2中有但表1中没有的;
3、交叉连接
(1)语法格式
select 查询列表
from 表1 别名
cross join 表2 别名;
(2)特点
类似于笛卡尔乘积
三、案例
1、内连接
(1)等值连接
① 查询员工名,部门名;
SELECT
last_name,
department_name
FROM
employees e
INNER JOIN departments d
ON e.`department_id` = d.`department_id` ;
② 查询名字中包含 e 的员工名和工种名(添加筛选)
SELECT
last_name,
job_title
FROM
employees e
INNER JOIN jobs j
ON e.`job_id` = j.`job_id`
WHERE e.`last_name` LIKE '%e%' ;
③ 查询部门个数 > 3 的城市名和部门个数(分组+筛选)
SELECT
city,
COUNT(*)
FROM
locations l
INNER JOIN departments d
ON l.`location_id` = d.`location_id`
GROUP BY l.`city`
HAVING COUNT(*) > 3 ;
④ 查询哪个部门的部门员工个数 > 3的部门名和员工个数,并按个数降序(排序)
SELECT
department_name,
COUNT(*)
FROM
departments d
INNER JOIN employees e
ON d.`department_id` = e.`department_id`
GROUP BY d.`department_name`
HAVING COUNT(*) > 3
ORDER BY COUNT(*) DESC ;
⑤ 查询员工名、部门名、工种名、并按部门名排序(多表连接)
SELECT
last_name,
department_name,
job_title
FROM
employees e
INNER JOIN departments d
ON e.`department_id` = d.`department_id`
INNER JOIN jobs j
ON e.`job_id` = j.`job_id`
ORDER BY department_name DESC ;
(2)非等值连接
① 查询员工的工资级别
SELECT
salary,
grade_level
FROM
employees e
INNER JOIN job_grades j
ON e.`salary` BETWEEN j.`lowest_sal`
AND j.`highest_sal` ;
② 查询工资级别的个数 > 2的个数,并且按工资级别降序
SELECT
COUNT(*),
grade_level
FROM
employees e
INNER JOIN job_grades j
ON e.`salary` BETWEEN j.`lowest_sal`
AND j.`highest_sal`
GROUP BY grade_level
HAVING COUNT(*) > 20
ORDER BY grade_level DESC ;
(3)自连接
① 查询员工的名字、上级的名字
SELECT
e.last_name,
m.last_name
FROM
employees e
INNER JOIN employees m
ON e.`manager_id` = m.`employee_id` ;
② 查询姓名中包含字符 k 的员工的名字、上级的名字
SELECT
e.last_name,
m.last_name
FROM
employees e
INNER JOIN employees m
ON e.`manager_id` = m.`employee_id`
WHERE e.`last_name` LIKE '%k%' ;
2、外连接
(1)左外连接
① 查询男朋友 不在男神表的女神名
SELECT
b.name,
bo.*
FROM
beauty b
LEFT OUTER JOIN boys bo
ON b.`boyfriend_id` = bo.`id`
WHERE bo.id IS NULL ;
② 查询哪个部门没有员工
SELECT
d.*,
e.`employee_id`
FROM
departments d
LEFT OUTER JOIN employees e
ON d.`department_id` = e.`department_id`
WHERE e.`department_id` IS NULL ;
(2)右外连接
SELECT
b.name,
bo.*
FROM
boys bo
RIGHT
OUTER JOIN beauty b
ON b.`boyfriend_id` = bo.`id`
WHERE bo.id IS NULL ;
(3)全外连接(MySQL不支持)
①
SELECT b.*, bo.*
FROM beauty b
FULL OUTER JOIN boys bo
ON b.`boyfriend_id` = bo.id;
3、交叉连接
交叉连接 == 笛卡尔乘积
①
SELECT b.*, bo.*
FROM beauty b
CROSS JOIN boys bo;
四、练习
1、查询编号 > 3 的女神们的男朋友信息,如果有则列出详细,如果没有,用null填充
SELECT b.*, bo.*
FROM beauty b
LEFT OUTER JOIN boys bo ON b.`boyfriend_id` = bo.`id`
WHERE b.`id` > 3;
2、查询哪个城市没有部门
SELECT
l.*,
d.*
FROM
locations l
LEFT OUTER JOIN departments d
ON l.`location_id` = d.`location_id`
WHERE d.`department_id` IS NULL ;
3、查询部门名为 SAL 或 IT 的员工信息
SELECT d.*, e.*
FROM departments d
LEFT OUTER JOIN employees e ON e.`department_id` = d.`department_id`
WHERE d.`department_name` IN ('SAL', 'IT');
五、总结
SQL92 VS SQL99
① 功能:SQL99支持的比较多;
② 可读性:SQL99 实现连接条件和筛选条件的分离,可读性较高;
七种 Join 连接