1. 笛卡尔积
当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数,是两张表条数的乘积,这种现象被称为:笛卡尔积现象。
-
笛卡尔积的错误会在下面条件下产生:
- 省略多个表的连接条件(或关联条件)
- 连接条件(或关联条件)无效
- 所有表中的所有行互相连接
-
为了避免笛卡尔积, 可以在 WHERE 加入有效的连接条件。 -
加入连接条件后,查询语法: SELECT table1.column, table2.column
FROM table1, table2
WHERE table1.column1 = table2.column2; #连接条件
-
从sql优化的角度,建议多表查询时,每个字段前都指明其所在的表。 -
可以给表起别名,在.SELECT和HERE中使用表的别名 SELECT t1.column, t2.column
FROM table1 t1, table2 t2 # t1、t2 为别名
WHERE t1.column1 = t2.column2;
如果给表起了别名,一旦在SELECT或WHERE中使用表名的话,则必须使用表的别名,而不能再使用表的原名。 -
如果有n个表实现多表的查询,则需要至少n-1个连接条件
2. 连接查询(最重要)
2.1 内连接
-
内连接:合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行 -
语法: SELECT 字段列表
FROM A表 INNER JOIN B表
ON 关联条件
WHERE 等其他子句;
-
SQL99语法实现内连接: # INNER 可省略
SELECT last_name,department_name
FROM employees e INNER JOIN departments d
ON e.`department_id` = d.`department_id`;
等值连接
-
案例:查询每个员工所在部门名称,显示员工名和部门名? #SQL92语法
#可以给表起别名,在SELECT和WHERE中使用表的别名。
SELECT emp.employee_id,dept.department_name,emp.department_id
FROM employees emp,departments dept
WHERE emp.`department_id` = dept.department_id;
#如果给表起了别名,一旦在SELECT或WHERE中使用表名的话,则必须使用表的别名,而不能再使用表的原名。
SQL92的缺点:结构不清晰,表的连接条件,和后期进一步筛选的条件,都放到where后面. # SQL99语法:inner可以省略
SELECT last_name,department_name
FROM employees e INNER JOIN departments d
ON e.`department_id` = d.`department_id`;
SQL99优点:表连接的条件是独立的,连接之后,如果还需要进一步筛选,再往后继续添加where
#SQL92语法
SELECT t1.column, t2.column
FROM table1 t1, table2 t2 # t1、t2 为别名
WHERE t1.column1 = t2.column2;
#SQL99语法
select
...
from
a
join
b
on
a和b连接的条件
where
筛选条件
非等值连接
- 案例:找出每个员工的薪资等级,要求显示员工名、薪资、薪资等级?
#SQL92语法#
SELECT e.last_name,e.salary,j.grade_level
FROM employees e,job_grades j
WHERE e.`salary` >= j.`lowest_sal` AND e.`salary` <= j.`highest_sal`;
自连接
# 查询员工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`;
内连接的等值连接:
- 完成能够匹配得上这个条件的数据查询出来。也就是如果一个部门没有员工,这个部门就不会显示。
- 如果我们需要将没有员工的部门也查询出来,那么就需要用到外连接。
2.2 外连接
- 外连接:合并具有同一列的两个以上的表的行, 结果集中除了包含一个表与另一个表匹配的行之外,还查询到了左表 或 右表中不匹配的行。
- 查询要求中含有所有这个修饰,如果涉及多张表,一般要使用外连接
- 外连接的分类:左外连接、右外连接、满外连接
- 左外连接:两个表在连接过程中除了返回满足连接条件的行以外还返回左表中不满足条件的行,这种连接称为左外连接。
- 右外连接:两个表在连接过程中除了返回满足连接条件的行以外还返回右表中不满足条件的行,这种连接称为右外连接。
左外连接
#SQL99语法实现外连接:
#练习:查询所有的员工的last_name,department_name信息
# 左外连接:
SELECT last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`;
- right 代表什么:表示将 join 关键字右边的这张表看成主表,主要是为了将这张表的数据全部查询出来,捎带着关联查询左边的表。
- 在外连接中,两张表连接,产生主次关系。
- 在内连接中,两张表平等,没有主次关系。
右外连接
#右外连接:
SELECT last_name,department_name
FROM employees e RIGHT OUTER JOIN departments d
ON e.`department_id` = d.`department_id`;
-
带有right的是右外连接,又叫做右连接 -
带有left的是左外连接,又叫做左连接 -
任何一个右连接都有左连接的写法。 -
任何一个左连接都有右连接的写法。 -
结果:(左右外连接一样)
思考:外连接的查询结果条数一定是>=内连接的查询结果条数? 正确。
UNION
2.3 7 种 SQL JOINS 的实现
# 中图:内连接
SELECT employee_id,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`;
# 左上图:左外连接
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`;
# 右上图:右外连接
SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`;
# 左中图:
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL;
# 右中图:
SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL;
# 左下图:满外连接
# 方式1:左上图 UNION ALL 右中图
SELECT employee_id,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
UNION ALL
SELECT employee_id,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL;
# 方式2:左中图 UNION ALL 右上图
SELECT employee_id,department_name
FROM employees e LEFT 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 RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`;
# 右下图:左中图 UNION ALL 右中图
SELECT employee_id,department_name
FROM employees e LEFT 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 RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL;
2.4 SQL99语法新特性(了解)
自然连接
-
SQL99 在 SQL92 的基础上提供了一些特殊语法,比如 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 NATURAL JOIN departments d;
USING连接
-
当我们进行连接的时候,SQL99还支持使用 USING 指定数据表里的 同名字段 进行等值连接。但是只能配合JOIN一起使用。比如: SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
USING (department_id);
-
你能看出与自然连接 NATURAL JOIN 不同的是,USING 指定了具体的相同的字段名称,你需要在 USING的括号 () 中填入要指定的同名字段。同时使用 JOIN…USING 可以简化 JOIN ON 的等值连接。它与下面的 SQL 查询结果是相同的: SELECT employee_id,last_name,department_name
FROM employees e ,departments d
WHERE e.department_id = d.department_id;
3. 总结
-
表连接的约束条件可以有三种方式:WHERE, ON, USING
- WHERE:适用于所有关联查询
- ON :(连接查询建议使用)只能和JOIN一起使用,只能写关联条件。虽然关联条件可以并到WHERE中和其他条件一起写,但分开写可读性更好。
- USING:只能和JOIN一起使用,而且要求两个关联字段在关联表中名称一致,而且只能表示关联字段值相等
-
注意:
我们要 控制连接表的数量 。多表连接就相当于嵌套 for 循环一样,非常消耗资源,会让 SQL 查询性能下降得很严重,因此不要连接不必要的表。在许多 DBMS 中,也都会有最大连接表的限制。
-
外连接时,连接谁取决于实际要求中的落脚点。啥时候用外连接,看看有无所有修饰词
- 显示所有员工的姓名,部门号和部门名称:外连接就是员工表
?
参考
https://www.bilibili.com/video/BV1iq4y1u7vj/?spm_id_from=333.337.search-card.all.click&vd_source=25b05e9bd8b4bdac16ca2f47bbeb7990
|