SQL必知必会(SQL99连接(JOIN))

SQL99 标准中的连接查询

一、交叉连接

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

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

SELECT * FROM player CROSS JOIN team;

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

SELECT * FROM t1 CROSS JOIN t2 CROSS JOIN t3;

二、自然连接

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

如果我们想把 player 表和 team 表进行等值连接,相同的字段是 team_id

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 两张表:

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;

一般来说在 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

SQL99 和 SQL92 的区别

至此我们讲解完了 SQL92 和 SQL99 标准下的连接查询,连接操作基本上可以分成三种情况:

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

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

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

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

SELECT ...
FROM table1
    JOIN 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、SQL Server 中是支持的。

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 中都对自连接处理进行了优化。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 在 SQL92 中是如何使用连接的 一、笛卡尔积 笛卡尔乘积是一个数学运算。假设我有两个集合 X 和 Y,那么 X...
    羋学僧阅读 1,239评论 0 3
  • 内容: 1. 了解常用的SQL标准. SQL存在不同的标准, 不同标准下的连接定义不同. 2. SQL92 标准 ...
    M_3ece阅读 6,805评论 0 2
  • 目录链接:https://www.jianshu.com/p/2c104aaadb03 常用的 SQL 标准 SQ...
    leacoder阅读 495评论 0 1
  • 二、sql99语法 /*语法:select 查询列表from 表1 别名 【连接类型】join 表2 别名on 连...
    雪上霜阅读 333评论 0 0
  • 表操作 创建表 修改表 添加列 删除列 删除表 表连接 关系型数据库,一个表就是数据之间的关系,而表与表的关系连接...
    adi0229阅读 362评论 0 1