交叉联接(CROSS JOIN)
最后将介绍另外一种不同类型的联接实际上它的语法不允许定义行匹配的条件
SELECT
loc_bookcase
loc_shelf
loc_position_left
bk_title
FROM location CROSS JOIN books
( row(s) affected)
这怎么可能呢?查询结果产生了行记录?在每一个表中仅有条记录啊!这是什么类型的联接呢?它就是交叉联接又称为笛卡尔积请回顾一下笛卡尔坐标系统它由两根互为直角的轴构成两轴交叉点的坐标为并从开始沿轴逐渐增加数值笛卡尔坐标系统的一个常见的例子就是国际象棋的棋盘它沿着轴用字母取代了数字除此之外两者是类似的
如果对棋盘上的每一个方格进行命名可以使用棋盘上的坐标AAEE等换句话说即将一个轴上的每一个值都与另外一个轴上的每一个值进行匹配这就是笛卡尔积(这非常类似于将轴上的值相乘:A×A×等)
CROSS JOIN对于两个表执行类似的操作它将一个表中的每一行与另外一个表中的每一行进行配对可以想象CROSS JOIN的结果集通常都相当大在上面的例子中仅仅交叉联接两个表(每个表只有行数据)就返回了行结果如果在查询中加入更多的表那么结果集将变得更加庞大
如何建立CROSS JOIN呢?实际上无需太多的语法使用旧式SQL语法来创建CROSS JOIN非常简单只需要在FROM子句中列出要选取的表无需任何JOIN条件
SELECT
loc_bookcase
loc_shelf
loc_position_left
bk_title
FROM locationbooks
也就是说无须使用任何JOIN关键字只需要在FROM子句中列出要交叉联接的表即可但是这会产生一个困境忽略WHERE子句将创建一个笛卡尔积的查询并且编写这样的SQL查询非常简单然而结果集可能会超出希望查询的数据范围表显示了将LIBRARY数据库中的表逐步增加到CROSS JOIN查询中时结果集数量的增长过程
表 LIBRARY数据库中的笛卡尔积
LIBRARY数据库非常小只包含个表其中没有一个表超过条记录但使用CROSSJOIN时却产生了极大的结果集设想一下如果对于一个包含了几十个甚至上百个表的产品级的数据库(其中可能包含了上百万的记录)使用CROSS JOIN将会产生什么样的后果?毫无疑问这会将数据库折磨到挂掉并让DBA恼火不已
可以在CROSS JOIN中使用一个WHERE子句来减少返回记录的数量例如使用下面的查询产生一个笛卡尔积
SELECT loc_bookcase loc_shelf loc_position_left bk_title
FROM location CROSS JOIN books
WHERE bk_id =
该查询仅返回条记录而不是前面例子中的条记录
幸运的是新的SQL语法要求首先显式地声明联接的类型这可以避免查询意外地产生不必要的笛卡尔积新SQL语法要求必须使用CROSS JOIN关键字或者应用联接条件对于DBA请注意以下的警告使用旧的联接语法对数据库是有害的很多RDBMS在它们各自的数据库中已经停止了对旧语法的支持除非需要处理遗留的代码否则在查询中最好不要再使用旧式语法
读者可能会感到疑惑如果CROSS JOIN是不良的应该避免使用的联接那为什么还要自寻烦恼地提供CROSS JOIN关键字呢?实际上CROSS JOIN也有合理的用途例如它提供了一个快速又简单的办法来产生巨量的数据集可用于测试用途另外一种应用场景是通过CROSS JOIN产生的数据集来选取行这些行既无法通过INNER JOIN也无法通过OUTER JOIN来产生例如选取对于指定产品的销售总量为的客户(或者在LIBRARY数据库的情形下查询在一年内没有借阅一本特定图书的客户)
CROSS JOIN是一个极为强大的工具因此也必须谨慎地加以使用处理巨大的数据集将消耗系统资源在SQL中最佳实践之一就是在查询中尽可能地对记录进行筛选并最小化须访问的数据的数量
一个SQL查询对于可以包含多少个JOIN操作是否存在限制呢?对于预备执行计划的复杂性都存在实际的限制更不用说执行这些复杂的计划可能会使服务器崩溃实际的数量取决于RDBMS以及运行RDBMS的硬件环境如果你发现联接太多的表那么应该重新考虑你的查询方案
返回目录SQL实战新手入门
编辑推荐
Oracle索引技术
高性能MySQL
数据仓库与数据挖掘培训视频教程