MySQL学习笔记——基础篇02:重点:多表查询

此章节为重点以及难点

文中标注理解的地方为本人理解,如有错误欢迎大佬指出。

目录

一、多表查询的分类

类别1:等值连接与非等值连接

等值连接

非等值连接

类别2:自连接

类别3:内连接与外连接(重点及难点,特别是外连接)

SQL99的多表查询语法

基本语法

外连接(OUTER JOIN)

UNION操作

去重方法,7种JOIN操作(放大招了)


一、多表查询的分类

类别1:等值连接与非等值连接

等值连接

例如:

代码:

SELECT employees.employee_id, employees.last_name, 
       employees.department_id, departments.department_id,
       departments.location_id
FROM   employees, departments
WHERE  employees.department_id = departments.department_id;

 解释:等值就是以两个表中相同的字段中元素值相等作为连接方式,即为一种一一对应的拼接方式。

补充:

1、表的别名

·使用表的别名可以简化查询

·列名前使用表名前缀可提高查询效率

SELECT e.employee_id, e.last_name, e.department_id,
       d.department_id, d.location_id
FROM   employees e , departments d
WHERE  e.department_id = d.department_id;

2、区分重复的列名(重点

·多个表中有相同列时,必须在列名之前加上表名前缀。

·在不同表中具有相同列名的列可以用表名加以区分。

SELECT employees.last_name, departments.department_name,employees.department_id
FROM employees, departments
WHERE employees.department_id = departments.department_id;

注意:推荐在任何情况下都在列名前加上表名,在大型工程中即便列名不同,在未来的操作中也有可能加入相同的列名导致程序报错,故在任何情况下都应加上表名并养成良好习惯。

非等值连接

问题引入:

在左图中显示了薪水(salary)的范围,在右图中显示了员工的薪水,那我们要将员工的薪水与薪水等级(grade_level)对应应该如何操作呢?

此时我们使用非等值连接的方式

代码:

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语句里可以看出判断条件是一个范围 即非等值匹配

类别2:自连接

自连接

当table1和table2本质上是同一张表,只是用取别名的方式虚拟成两张表以代表不同的意义。然后两个表再进行内连接,外连接等查询

举例:自己查自己,比如员工资料中有主管的员工号,而主管也是员工,这样就可以通过表自查查询员工所对应的主管和主管信息。

代码举例:

SELECT worker.last_name , manager.last_name
FROM   employees worker, employees manager
WHERE  worker.manager_id = manager.employee_id ;

类别3:内连接与外连接(重点及难点,特别是外连接)

内连接: 合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行

外连接: 两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行 ,这种连接称为左(或右) 外连接。没有匹配的行时, 结果表中相应的列为空(NULL)。

如果是左外连接,则连接条件中左边的表也称为主表,右边的表称为从表

如果是右外连接,则连接条件中右边的表也称为主表,左边的表称为从表

外连接通俗解释:两张表比较起来如果左表数据量更多,则右表一定有缺少的数据项(NULL)此时进行左外连接,则可以把那些NULL的数据项也显示出来。相当于把左右两边的数据量用NULL补充得一样多。

SQL99的多表查询语法

基本语法

使用JOIN...ON创建连接:
举例:

SELECT table1.column, table2.column,table3.column
FROM table1
    JOIN table2 
ON table1 和 table2 的连接条件
    JOIN table3 
ON table2 和 table3 的连接条件

说明

  • 可以使用 ON 子句指定额外的连接条件

  • 这个连接条件是与其它条件分开的。

  • ON 子句使语句具有更高的易读性

  • 关键字 JOIN、INNER JOIN、CROSS JOIN 的含义是一样的,都表示内连接

补充:当你使用WHERE时一般跟在最后一个ON的后面,即把要查的表全部添加完成后使用WHERE,如不这样操作可能会导致程序可以运行但结果错误。

个人理解:JOIN...ON其实还是属于FROM的一部分,根据WHERE紧随FROM的准则,WHRER应在全部表加入后再进行。

内连接的语法

SELECT 字段列表
FROM A表 INNER JOIN B表
ON 关联条件
WHERE 等其他子句;

当JOIN前未加任何限制时默认为内连接。

外连接(OUTER JOIN)

1.左外连接(LEFT JOIN)

#实现查询结果是A
SELECT 字段列表
FROM A表 LEFT JOIN B表
ON 关联条件
WHERE 等其他子句;

2.右外连接(RIGHT JOIN)

#实现查询结果是B
SELECT 字段列表
FROM A表 RIGHT JOIN B表
ON 关联条件
WHERE 等其他子句;

3.满外连接(FULL OUTER JOIN)

满外连接的结果 = 左右表匹配的数据 + 左表没有匹配到的数据 + 右表没有匹配到的数据。

SQL99是支持满外连接的。使用FULL JOIN 或 FULL OUTER JOIN来实现。

需要注意的是,MySQL不支持FULL JOIN,但是可以用 LEFT JOIN UNION RIGHT join代替。

UNION操作

利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组合成单个结果集。合并时,两个表对应的列数和数据类型必须相同,并且相互对应。各个SELECT语句之间使用UNION或UNION ALL关键字分隔。

SELECT column,... FROM table1
UNION [ALL]
SELECT column,... FROM table2

UNION返回结果集的并集,去除重复记录

UNION ALL 返回结果集的并集,不去除重复记录(两个集合的共有部分叠加了两次)

注意:执行UNION ALL语句时所需要的资源比UNION语句少。如果明确知道合并数据后的结果数据不存在重复数据,或者不需要去除重复的数据,则尽量使用UNION ALL语句,以提高数据查询的效率。

由于我们可以用 JOIN 实现去重,所以推荐使用UNION ALL。

去重方法,7种JOIN操作(放大招了)

 中图:内连接

SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`;

解释:正常的取交集连接,无理解困难。

左上图:左外连接

#左上图:左外连接
SELECT employee_id,last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`;

解释:想要显示出完整左表,此时使用左外连接,右表缺失的部分用NULL补足。

可以看到右表缺省的部位用NULL补齐了 

右上图:右外连接

#右上图:右外连接
SELECT employee_id,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`;

解释:与左上一致。

左中图:

#左中图:A - A∩B
SELECT employee_id,last_name,department_name
FROM employees e LEFT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE d.`department_id` IS NULL

解释:此刻要求左表中没有与右表有共同值的数据项,先看上面我左外连接的解释,此时左外连接中左表对应右表的NULL,那么加上`WHERE d.`department_id` IS NULL`这个条件语句就可以把左表对应右表NULL的数据项全部筛选出来。

 右中图

#右中图:B-A∩B
SELECT employee_id,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL

左下:

#左下图:满外连接
# 左中图 + 右上图  A∪B
SELECT employee_id,last_name,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,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`;

解释,看原图得知,左中图加右上图拼接的话不会有重复数据,所以直接使用UNION ALL。这就是我们自己去重的方法

右下图

#右下图
#左中图 + 右中图  A ∪B- A∩B 或者 (A -  A∩B) ∪ (B - A∩B)
SELECT employee_id,last_name,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,last_name,department_name
FROM employees e RIGHT JOIN departments d
ON e.`department_id` = d.`department_id`
WHERE e.`department_id` IS NULL

 把两张表互相存在不对应的项全部表示出来了。

最后我们要注意:

我们要控制连接表的数量。多表连接就相当于嵌套 for 循环一样,非常消耗资源,会让 SQL 查询性能下降得很严重,因此不要连接不必要的表。在许多 DBMS 中,也都会有最大连接表的限制。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值