上节课我们讲解了 SQL92 标准,在它之后又提出了 SQL99标准。现在各大 DBMS 中对 SQL99 标准的支持度更好。你一定听说过 LEFT JOIN、RIGHT JOIN 这样的操作符,这实际上就是 SQL99 的标准,在 SQL92 中它们是用(+)代替的。SQL92 和 SQL99 标准原理类似,只是 SQL99 标准的可读性更强。

今天我就来讲解一下 SQL99 标准中的连接查询,在今天的课程中你需要重点掌握以下几方面的内容:

  1. SQL99 标准下的连接查询是如何操作的?
  2. SQL99 与 SQL92 的区别是什么?
  3. 在不同的 DBMS 中,使用连接需要注意什么?

SQL99 标准中的连接查询

上一篇文章中,我用 NBA 球员的数据表进行了举例,包括了三张数据表 player、team 和 height_grades。

其中 player 表为球员表,一共有 37 个球员,如下所示:

team 表为球队表,一共有 3 支球队,如下所示:

height_grades 表为身高等级表,如下所示:

接下来我们看下在 SQL99 标准中,是如何进行连接查询的?

交叉连接

交叉连接实际上就是 SQL92 中的笛卡尔乘积,只是这里我们采用的是 CROSS JOIN。

我们可以通过下面这行代码得到 player 和 team 这两张表的笛卡尔积的结果:

SQL: SELECT * FROM player CROSS JOIN team

运行结果(一共 37*3=111 条记录):

如果多张表进行交叉连接,比如表 t1,表 t2,表 t3 进行交叉连接,可以写成下面这样:

SQL: SELECT * FROM t1 CROSS JOIN t2 CROSS JOIN t3

自然连接

你可以把自然连接理解为 SQL92 中的等值连接。它会帮你自动查询两张连接表中所有相同的字段,然后进行等值连接。

如果我们想把 player 表和 team 表进行等值连接,相同的字段是 team_id。还记得在 SQL92 标准中,是如何编写的么?

SELECT player_id, a.team_id, player_name, height, team_name FROM player as a, team as b WHERE a.team_id = b.team_id

在 SQL99 中你可以写成:

SELECT player_id, team_id, player_name, height, team_name FROM player NATURAL JOIN team

实际上,在 SQL99 中用 NATURAL JOIN 替代了 WHERE player.team_id = team.team_id。

ON 连接

ON 连接用来指定我们想要的连接条件,针对上面的例子,它同样可以帮助我们实现自然连接的功能:

SELECT player_id, player.team_id, player_name, height, team_name FROM player JOIN team ON player.team_id = team.team_id

这里我们指定了连接条件是ON player.team_id = team.team_id,相当于是用 ON 进行了 team_id 字段的等值连接。

当然你也可以 ON 连接进行非等值连接,比如我们想要查询球员的身高等级,需要用 player 和 height_grades 两张表:

SQL99:SELECT p.player_name, p.height, h.height_level
FROM player as p JOIN height_grades as h
ON height BETWEEN h.height_lowest AND h.height_highest

这个语句的运行结果和我们之前采用 SQL92 标准的查询结果一样。

SQL92:SELECT p.player_name, p.height, h.height_level
FROM player AS p, height_grades AS h
WHERE p.height BETWEEN h.height_lowest AND h.height_highest

一般来说在 SQL99 中,我们需要连接的表会采用 JOIN 进行连接,ON 指定了连接条件,后面可以是等值连接,也可以采用非等值连接。

USING 连接

当我们进行连接的时候,可以用 USING 指定数据表里的同名字段进行等值连接。比如:

SELECT player_id, team_id, player_name, height, team_name FROM player JOIN team USING(team_id)

你能看出与自然连接 NATURAL JOIN 不同的是,USING指定了具体的相同的字段名称,你需要在 USING 的括号 ()中填入要指定的同名字段。同时使用 JOIN USING 可以简化 JOIN ON 的等值连接,它与下面的 SQL 查询结果是相同的:

SELECT player_id, player.team_id, player_name, height, team_name FROM player JOIN team ON player.team_id = team.team_id

外连接

SQL99 的外连接包括了三种形式:

  1. 左外连接:LEFT JOIN 或 LEFT OUTER JOIN
  2. 右外连接:RIGHT JOIN 或 RIGHT OUTER JOIN
  3. 全外连接:FULL JOIN 或 FULL OUTER JOIN

我们在 SQL92 中讲解了左外连接、右外连接,在 SQL99中还有全外连接。全外连接实际上就是左外连接和右外连接的结合。在这三种外连接中,我们一般省略 OUTER 不写。

1. 左外连接

SQL92

SELECT * FROM player, team where player.team_id = team.team_id(+)

SQL99

SELECT * FROM player LEFT JOIN team ON player.team_id = team.team_id

2. 右外连接

SQL92

SELECT * FROM player, team where player.team_id(+) = team.team_id

SQL99

SELECT * FROM player RIGHT JOIN team ON player.team_id = team.team_id

3. 全外连接

SQL99

SELECT * FROM player FULL JOIN team ON player.team_id = team.team_id

需要注意的是 MySQL 不支持全外连接,否则的话全外连接会返回左表和右表中的所有行。当表之间有匹配的行,会显示内连接的结果。当某行在另一个表中没有匹配时,那么会把另一个表中选择的列显示为空值。

也就是说,全外连接的结果 = 左右表匹配的数据 + 左表没有匹配到的数据 + 右表没有匹配到的数据。

自连接

自连接的原理在 SQL92 和 SQL99 中都是一样的,只是表述方式不同。

比如我们想要查看比布雷克·格里芬身高高的球员都有哪些,在两个 SQL 标准下的查询如下。
SQL92

SELECT b.player_name, b.height FROM player as a , player as b WHERE a.player_name = '布雷克-格里芬' and a.height < b.height

SQL99

SELECT b.player_name, b.height FROM player as a JOIN player as b ON a.player_name = '布雷克-格里芬' and a.height < b.height

运行结果(6 条记录):

SQL99 和 SQL92 的区别

至此我们讲解完了 SQL92 和 SQL99 标准下的连接查询,它们都对连接进行了定义,只是操作的方式略有不同。我们再来回顾下,这些连接操作基本上可以分成三种情况:

  1. 内连接:将多个表之间满足连接条件的数据行查询出来。它包括了等值连接、非等值连接和自连接。
  2. 外连接:会返回一个表中的所有记录,以及另一个表中匹配的行。它包括了左外连接、右外连接和全连接。
  3. 交叉连接:也称为笛卡尔积,返回左表中每一行与右表中每一行的组合。在 SQL99 中使用的 CROSS JOIN。

不过 SQL92 在这三种连接操作中,和 SQL99 还存在着明显的区别。

首先我们看下 SQL92 中的 WHERE 和 SQL99 中的 JOIN。

你能看出在 SQL92 中进行查询时,会把所有需要连接的表都放到 FROM 之后,然后在 WHERE 中写明连接的条件。而 SQL99 在这方面更灵活,它不需要一次性把所有需要连接的表都放到 FROM 之后,而是采用 JOIN 的方式,每次连接一张表,可以多次使用 JOIN 进行连接。

另外,我建议多表连接使用 SQL99 标准,因为层次性更强,可读性更强,比如:

SELECT ...
FROM table1JOIN 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

SQL99 采用的这种嵌套结构非常清爽,即使再多的表进行连接也都清晰可见。如果你采用 SQL92,可读性就会大打折扣。

最后一点就是,SQL99 在 SQL92 的基础上提供了一些特殊语法,比如 NATURAL JOIN 和 JOIN USING。它们在实际中是比较常用的,省略了 ON 后面的等值条件判断,让SQL 语句更加简洁。

不同 DBMS 中使用连接需要注意的地方

SQL 连接具有通用性,但是不同的 DBMS 在使用规范上会存在差异,在标准支持上也存在不同。在实际工作中,你需要参考你正在使用的 DBMS 文档,这里我整理了一些需要注意的常见的问题。

1. 不是所有的 DBMS 都支持全外连接

虽然 SQL99 标准提供了全外连接,但不是所有的 DBMS 都支持。不仅 MySQL 不支持,Access、SQLite、MariaDB等数据库软件也不支持。不过在 Oracle、DB2、SQLServer 中是支持的。

2.Oracle 没有表别名 AS

为了让 SQL 查询语句更简洁,我们经常会使用表别名 AS,不过在 Oracle 中是不存在 AS 的,使用表别名的时候,直接在表名后面写上表别名即可,比如 player p,而不是player AS p。

3.SQLite 的外连接只有左连接

SQLite 是一款轻量级的数据库软件,在外连接上只支持左连接,不支持右连接,不过如果你想使用右连接的方式,比如table1 RIGHT JOIN table2,在 SQLite 你可以写成table2 LEFT JOIN table1,这样就可以得到相同的效果。

除了一些常见的语法问题,还有一些关于连接的性能问题需要你注意:

1. 控制连接表的数量

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

2. 在连接时不要忘记 WHERE 语句

多表连接的目的不是为了做笛卡尔积,而是筛选符合条件的数据行,因此在多表连接的时候不要忘记了 WHERE 语句,这样可以过滤掉不必要的数据行返回。

3. 使用自连接而不是子查询

我们在查看比布雷克·格里芬高的球员都有谁的时候,可以使用子查询,也可以使用自连接。一般情况建议你使用自连接,因为在许多DBMS 的处理过程中,对于自连接的处理速度要比子查询快得多。你可以这样理解:子查询实际上是通过未知表进行查询后的条件判断,而自连接是通过已知的自身数据表进行条件判断,因此在大部分 DBMS 中都对自连接处理进行了优化。

总结

连接可以说是 SQL 中的核心操作,通过两篇文章的学习,你已经从多个维度对连接进行了了解。同时,我们对 SQL的两个重要标准 SQL92 和 SQL99 进行了学习,在我们需要进行外连接的时候,建议采用 SQL99 标准,这样更适合阅读。

此外我还想强调一下,我们在进行连接的时候,使用的关系型数据库管理系统,之所以存在关系是因为各种数据表之间存在关联,它们并不是孤立存在的。在实际工作中,尤其是做业务报表的时候,我们会用到 SQL 中的连接操作(JOIN),因此我们需要理解和熟练掌握 SQL 标准中连接的使用,以及不同 DBMS 中对连接的语法规范。剩下要做的,就是通过做练习和实战来增强你的经验了,做的练习多了,也就自然有感觉了。

扩展;
完整的SELECT语句内部执行顺序是:
1、FROM子句组装数据(包括通过ON进行连接)
2、WHERE子句进行条件筛选
3、GROUP BY分组
4、使用聚集函数进行计算;
5、HAVING筛选分组;
6、计算所有的表达式;
7、SELECT 的字段;
8、ORDER BY排序
9、LIMIT筛选

【SQL语法基础】SQL99是如何使用连接的,与SQL92的区别是什么?相关推荐

  1. SQL语法基础之ALTER语句

    SQL语法基础之ALTER语句 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查看ALTER的帮助信息 mysql> ? ALTER Many help items fo ...

  2. SQL——语法基础篇(上)

    虽然 SQL 是声明式语言,我们可以像使用英语一样使用它,不过在 RDBMS(关系型数据库管理系统)中,SQL 的实现方式还是有差别的.今天我们就从数据库的角度来思考一下 SQL 是如何被执行的. O ...

  3. 【SQL语法基础】了解SQL:一门半衰期很长的语言

    在我们的日常工作中,使用的是类似 MySQL.Oracle 这种的数据库管理系统,实际上这些数据库管理系统都遵循 SQL 语言,这就意味着,我们在使用这些数据库的时候,都是通过 SQL 语言与它们打交 ...

  4. 【SQL语法基础】视图在SQL中的作用是什么,它是怎样工作的?

    我们之前对 SQL 中的数据表查询进行了讲解,今天我们来看下如何对视图进行查询.视图,也就是我们今天要讲的虚拟表,本身是不具有数据的,它是 SQL 中的一个重要概念.从下面这张图中,你能看到,虚拟表的 ...

  5. 【SQL语法基础】数据过滤:SQL数据过滤都有哪些方法?

    我在上篇文章中讲到过,提升查询效率的一个很重要的方式,就是约束返回结果的数量,还有一个很有效的方式,就是指定筛选条件,进行过滤.过滤可以筛选符合条件的结果,并进行返回,减少不必要的数据行. 那么在今天 ...

  6. Oracle-PL/SQL语法基础

    set serveroutput on;--条件控制(if-then-else) 属性类型(%type) 输出 declarestu_name students.s_name%type; begins ...

  7. sql语法基础,sql分组查询

    01分组查询–group by 格式: SELECT 列名1,列名2,... FROM 表名 GROUP BY 列名1,列名2.... 例一,按照商品种类统计一下行数 SELECT product_t ...

  8. 【SQL语法基础】初识事务隔离:隔离的级别有哪些,它们都解决了哪些异常问题?

    上一篇文章中,我们讲到了事务的四大特性 ACID,分别是原子性.一致性.隔离性和持久性,其中隔离性是事务的基本特性之一,它可以防止数据库在并发处理时出现数据不一致的情况.最严格的情况下,我们可以采用串 ...

  9. 【SQL语法基础】王者荣耀英雄数据表

    文章目录 heros heros_data_with_structure heros_play heros_temp heros INSERT INTO `heros` VALUES (10000, ...

最新文章

  1. iPhone中字符串的国际化
  2. 很久没有更新blog了,对不起每一位朋友。
  3. Android 自定义字体,设置字体
  4. css摇曳的_HTML5+CSS3实现树被风吹动摇晃
  5. jQuery 的属性操作方法
  6. UI实用素材|扁平化UI设计模板,UI设计师都要会!
  7. 换了路由器电脑都连不上网了_换了新路由器电脑连不上网
  8. nginx IP 443 路由到其它地址
  9. ERP九大流程图(图)
  10. 图像匹配论文与方法超全整理
  11. 论“詹姆斯*哈登”到底是不是球队毒瘤
  12. cad卸载不干净_还怕软件卸载不干净吗?试试它:Revo Uninstaller Pro
  13. windows共享 无法访问
  14. hdu5294||2015多校联合第一场1007 最短路+最大流
  15. 常用的7个计算机网络命令
  16. 用笔记本做wifi热点
  17. 人工智能技术在电气自动化中的应用,主要有哪些?
  18. 细说 AppbarLayout,如何理解可折叠 Toolbar 的定制
  19. 华为鸿蒙OS正式发布!教你如何升级
  20. 【开赛啦!邀你来战 】2022年“桂林银行杯”数据建模大赛暨全国大学生数学建模竞赛广西赛区热身赛

热门文章

  1. 北方计算机专修学院“展示自我 秀出风采” 网页创意设计大赛成功举办
  2. linux发展现状和学习建议
  3. 软件测试质量提升方案(初稿)
  4. 差分隐私 深度学习_深度学习中的差异隐私
  5. 网页JavaScript特效之flappy bird(像素鸟)
  6. 谷歌相机第一个版本_您的第一个Google地图
  7. 帆软FineReport本地部署springboot
  8. chrome浏览器页面自动翻译页面失效问题解决
  9. java连接memcached_Memcached连接
  10. Oracle 宣布 JDK 11 将把 JavaFX 分离成独立模块