又称多表查询,即当查询中涉及到了多个表的字段,需要使用多表连接。
如果这样写法,将会导致笛卡尔乘积现象
SELECT
字段 1,字段2
FROM
表 1,表2,
...;
笛卡尔乘积现象: 当查询多个表时,没有添加有效的连接条件,导致多个表所有行实现完全连接(表1有m行,表2有n行,结果有m*n行)
发生原因: 没有有效的连接条件
如何解决: 添加有效的连接条件
1.按年代分类:
sql92标准:仅仅支持内连接
sql99标准【推荐使用】:支持内连接、外连接(左外,右外)、交叉连接
2.按功能分类
内连接:等值、非等值、自连接
外连接:、左外、右外、全外(mysql不支持)
交叉连接
语法:
SELECT
查询列表
FROM
表 1 别名,表 2 别名
WHERE
表 1.key =表 2.key
【 AND 筛选条件】
【 GROUP BY分组字段】
【 HAVING分组后的筛选】
【 ORDER BY排序字段】;
SELECT
`name`,
boyName
FROM
beauty,
boys
WHERE
beauty.boyfriend_id = boys.id;
案例2:查询员工名对应的部门名
SELECT
last_name,
department_name
FROM
employees,
departments
WHERE
employees.department_id = departments.department_id;
案例3:查询员工名、工种号、工种名
SELECT
last_name,
j.job_id,
job_title
FROM
employees AS e,
jobs AS j
WHERE
e.job_id = j.job_id;
案例4:查询有奖金的员工名、部门名
SELECT
last_name,
department_name
FROM
employees,
departments
WHERE
employees.department_id = department.department_id
AND employees.commission_pct IS NOT NULL;
案例5:查询每个城市的部门个数
SELECT
city AS 个数,
COUNT(*)
FROM
location AS l,
departments AS d
WHERE
l.department_id = d.department_id
GROUP BY
city;
案例6:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
SELECT
department_name,
d.manager_id,
MIN( salary )
FROM
departments AS d,
employees AS e
WHERE
d.departmrnt_id = e.department_id
AND e.commission_pct IS NOT NULL
GROUP BY
department_name,
d.manager_id;
特点:
① 一般为表起别名
②多表的顺序可以调换
③n表连接至少需要n-1个连接条件
④等值连接的结果是多表的交集部分
语法:
SELECT
查询列表
FROM
表 1 别名,表 2 别名
WHERE
非等值的连接条件
【 AND 筛选条件】
【 GROUP BY分组字段】
【 HAVING分组后的筛选】
【 ORDER BY排序字段】;
案例:查询员工的工资和工资级别
SELECT
salary,
grade_level
FROM
employees AS e,
job_grades AS j
WHERE
e.salary BETWEEN j.lowest_sal
AND j.highest_sal;
语法:
SELECT
查询列表
FROM
表 别名 1,表 别名 2
WHERE
等值的连接条件
【 AND 筛选条件】
【 GROUP BY分组字段】
【 HAVING分组后的筛选】
【 ORDER BY排序字段】;
案例:查询员工名和上级的名称
SELECT
e.last_name,
m.last_name
FROM
employee AS e,
employees AS m
WHERE
e.manager_id = m.employee_id;
语法:
SELECT
查询列表
FROM
表 1 别名
INNER JOIN 表 2 别名 ON 连接条件
WHERE
筛选条件
GROUP BY
分组列表
HAVING
分组后的筛选
ORDER BY
排序列表
LIMIT 子句;
特点:
①表的顺序可以调换
②内连接的结果=多表的交集
③n表连接至少需要n-1个连接条件
分类:
等值连接
#案例1:查询员工名、部门名(调换位置)
SELECT
last_name,
department_name
FROM
employees e
INNER JOIN departments d ON e.department_id = d.department_id;
#案例2:查询名字中包含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
departments d
INNER JOIN locations l ON d.location_id = l.location.id
GROUP BY
city
HAVING
COUNT(*) >;
非等值连接
#案例1:查询员工的工资级别
SELECT
salary,
grade_level
FROM
employees e
INNER JOIN job_grades j ON e.salary BETWEEN j.lowest_sal
AND highest_sal;
#案例2:查询每个工资级别个数>20的个数,并且按工资级别降序
SELECT
count(*),
grade_level
FROM
employees e
INNER JOIN job_grades j ON e.salary BETWEEN j.lowest_sal
AND highest_sal
GROUP BY
grade_level
HAVING
count(*)> 20
ORDER BY
grade_level DESC;
自连接
#案例:查询员工的名字、上级的名字
SELECT
e.last_name,
m.last_name
FROM
employees e
INNER JOIN employees m ON e.manager_id = m.employee_id;
应用场景:用于查询一个表中有,另一个表中没有的记录
左外连接:left【outer】
右外连接:right【outer】
全外连接:full【outer】
语法:
SELECT
查询列表
FROM
表 1 别名 LEFT | RIGHT |
FULL【OUTER】 JOIN 表 2 别名 ON 连接条件
WHERE
筛选条件
GROUP BY
分组列表
HAVING
分组后的筛选
ORDER BY
排序列表
LIMIT 子句;
#案例:查询哪个部门没有员工
#左外连接
SELECT
d.*,
e.employee_id
FROM
departments d
LEFT OUTER JOIN employees e ON d.department_id = e.department_id
WHERE
e.employee_id IS NULL;
#右外连接
SELECT
d.*,
e.employee_id
FROM
employees e
LEFT OUTER JOIN departments d ON d.department_id = e.department_id
WHERE
e.employee_id IS NULL;
特点:
①查询的结果=主表中所有的行,如果从表和它匹配的将显示匹配行,如果从表没有匹配的则显示null
②left join 左边的就是主表,right join 右边的就是主表,full join 两边都是主表
③一般用于查询除了交集部分的剩余的不匹配的行
④全外连接=内连接的结果+表1中有但表2中没有的+表2中有但表1中没有的
语法:
SELECT
查询列表
FROM
表 1 别名
CROSS JOIN 表 2 别名;
特点: 类似于笛卡尔乘积