交叉聯接(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
數據倉庫與數據挖掘培訓視頻教程
From:http://tw.wingwit.com/Article/program/SQL/201311/16467.html