SQL学习九
1.SQL99 标准下的连接查询是如何操作的?
交叉连接
交叉连接实际上就是 SQL92 中的笛卡尔乘积,只是这里我们采用的是 CROSS JOIN。
SQL: SELECT * FROM player CROSS JOIN team
自然连接
你可以把自然连接理解为 SQL92 中的等值连接。它会帮你自动查询两张连接表中所有相同的字段,然后进行等值连接。
92
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
99
SELECT player_id, team_id, player_name, height, team_name FROM player NATURAL JOIN team
ON 连接
ON 连接用来指定我们想要的连接条件,针对上面的例子,它同样可以帮助我们实现自然连接的功能:
SELECT player_id, player.team_id, player_name, height, team_name FROM player JOIN team ON player.team_id = team.team_id
一般来说在 SQL99 中,我们需要连接的表会采用 JOIN 进行连接,ON 指定了连接条件,后面可以是等值连接,也可以采用非等值连接。
USING 连接
当我们进行连接的时候,可以用 USING 指定数据表里的同名字段进行等值连接。
SELECT player_id, team_id, player_name, height, team_name FROM player JOIN team USING(team_id)
同时使用 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 的外连接包括了三种形式:
左外连接:LEFT JOIN 或 LEFT OUTER JOIN
右外连接:RIGHT JOIN 或 RIGHT OUTER JOIN
全外连接:FULL JOIN 或 FULL OUTER JOIN
1. 左外连接
SQL 92
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
自连接
自连接的原理在 SQL92 和 SQL99 中都是一样的,只是表述方式不同。
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
2.SQL99 与 SQL92 的区别是什么?
内连接:将多个表之间满足连接条件的数据行查询出来。它包括了等值连接、非等值连接和自连接。
外连接:会返回一个表中的所有记录,以及另一个表中匹配的行。它包括了左外连接、右外连接和全连接。
交叉连接:也称为笛卡尔积,返回左表中每一行与右表中每一行的组合。在 SQL99 中使用的 CROSS JOIN。
3.在不同的 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 中都对自连接处理进行了优化。
查询不同身高级别(对应 height_grades 表)对应的球员数量(对应 player 表)。