Oracle 查詢結果集行數分析

来源:http://www.cnblogs.com/hanzongze/archive/2017/06/23/oracle-sql-rows.html
-Advertisement-
Play Games

本人曾去某金融軟體公司面試,交流中面試官問的一個問題是:“如果有 A、B 兩張表,A 表中有 2 條數據,B 表中有 200 條數據,請問 SELECT FROM A,B 能查出多少條數據?”。 聽到這個問題的瞬間我就懵了,因為我自己也做過近兩年的面試官,所以我首先會想的就是他問這麼沒有實際意義(實 ...


本人曾去某金融軟體公司面試,交流中面試官問的一個問題是:“如果有 A、B 兩張表,A 表中有 2 條數據,B 表中有 200 條數據,請問 SELECT * FROM A,B 能查出多少條數據?”。

聽到這個問題的瞬間我就懵了,因為我自己也做過近兩年的面試官,所以我首先會想的就是他問這麼沒有實際意義(實際開發中幾乎 100% 的查詢都需要條件)的問題是想考察我什麼呢?同時我心裡也在想,這種逗號的寫法本質上就是內連接,那答案是笛卡爾積嗎?我剛想對面試官說:“我沒這麼寫過,但我分析這種寫法的結果應該是笛卡爾積,也就是 2×200 等於 400……”,正在組織語言的時候被面試官打斷了,他說:“沒關係!我就問問!……”

現在我們來仔細研究下這個問題

首先來創建 t6、t7、t8 共 3 張表,創建語句如下:

CREATE TABLE t6 AS SELECT LEVEL f1,6 f2,0 f3 FROM DUAL CONNECT BY LEVEL<=6;
CREATE TABLE t7 AS SELECT LEVEL f1,7 f2,0 f3 FROM DUAL CONNECT BY LEVEL<=7;
CREATE TABLE t8 AS SELECT LEVEL f1,8 f2,0 f3 FROM DUAL CONNECT BY LEVEL<=8;

然後來看看各個表中的數據分步

SQL> SELECT t6.* FROM t6;

        F1         F2         F3
---------- ---------- ----------
         1          6          0
         2          6          0
         3          6          0
         4          6          0
         5          6          0
         6          6          0

6 rows selected

SQL> SELECT t7.* FROM t7;

        F1         F2         F3
---------- ---------- ----------
         1          7          0
         2          7          0
         3          7          0
         4          7          0
         5          7          0
         6          7          0
         7          7          0

7 rows selected

SQL> SELECT t8.* FROM t8;

        F1         F2         F3
---------- ---------- ----------
         1          8          0
         2          8          0
         3          8          0
         4          8          0
         5          8          0
         6          8          0
         7          8          0
         8          8          0

8 rows selected

接下來開始我們的實驗

SELECT COUNT(1) res FROM t6 JOIN t7 ON t6.f1=t7.f1; -- res: 6
SELECT COUNT(1) res FROM t6 JOIN t7 ON t6.f2=t7.f2; -- res: 0
SELECT COUNT(1) res FROM t6 JOIN t7 ON t6.f3=t7.f3; -- res: 42
SELECT COUNT(1) res FROM t6 JOIN t7 ON 1=1; -- res: 42
SELECT COUNT(1) res FROM t6 JOIN t7 ON 1=2; -- res: 0

在 t6 和 t7 兩張表中:f1 欄位值中的 1~6 是相等的,所以結果集行數是 6×1 等於 6;f2 欄位值則完全不想等,所以結果集行數是 6×0 等於 0;f3 欄位值全都相等,所以結果集行數是 6×7 等於 42。

SELECT COUNT(1) res FROM t6 LEFT JOIN t7 ON t6.f1=t7.f1; -- res: 6
SELECT COUNT(1) res FROM t6 LEFT JOIN t7 ON t6.f2=t7.f2; -- res: 6
SELECT COUNT(1) res FROM t6 LEFT JOIN t7 ON t6.f3=t7.f3; -- res: 42
SELECT COUNT(1) res FROM t6 LEFT JOIN t7 ON 1=1; -- res: 42
SELECT COUNT(1) res FROM t6 LEFT JOIN t7 ON 1=2; -- res: 6

左連接的時候,會返回左邊表中的所有行,如果左邊表中的行在右邊表中沒有匹配行,則結果集中右邊表中的列返回空值。在這裡,t7.f1 與 t6.f1 有 6 行唯一匹配,所以結果集行數是 6×1 等於 6;t7.f2 與 t6.f2 完全不匹配,所以結果集行數就是 6;t7.f3 中有 7 行能匹配 t6.f3 中的任意行,所以結果集行數是 6×7 等於 42。

接下來回到本文一開始提出的那個問題,先看查詢結果:

SELECT COUNT(1) res FROM t6,t7; -- res: 42

事實上這是一個交叉連接(一定有人會暈倒),交叉連接的標準寫法是:

SELECT COUNT(1) res FROM t6 CROSS JOIN t7; -- res: 42

也許是工作久了的原因,可能大部分人都還記得內連接和外連接(左連接、右連接、全連接),因為內鏈接和左連接還經常用。同時,估計大部分人和我一樣,已經把三大連接中的交叉連接給忘得一干二凈了,原因也很簡單,長時間沒用了!

交叉連接最典型的特點就是沒有 WHERE 子句,交叉連接返回連接表中所有數據行的笛卡爾積,在關係資料庫中的笛卡爾積的結果就是交叉連接所涉及的表中行數之積。

其實 CROSS JOIN 後面也是可以跟 WHERE 子句的,不過那樣它就相當於內連接了。我覺得可以理解為不寫條件就相當於條件恆等,這時的結果集行數就是兩個表中數據行數的乘積,也就是所謂的笛卡爾積。

最後附上同樣從來都用不到的全連接的驗證結果

SELECT COUNT(1) res FROM t6 FULL JOIN t7 ON t6.f1=t7.f1; -- res: 7
SELECT COUNT(1) res FROM t6 FULL JOIN t7 ON t6.f2=t7.f2; -- res: 13
SELECT COUNT(1) res FROM t6 FULL JOIN t7 ON t6.f3=t7.f3; -- res: 42
SELECT COUNT(1) res FROM t6 FULL OUTER JOIN t7 ON 1=1; -- res: 42
SELECT COUNT(1) res FROM t6 FULL OUTER JOIN t7 ON 1=2; -- res: 13

最最後附上全連接的定義:完全外部連接返回左邊表和右邊表中的所有行。當某行在一個表中沒有匹配行時,則另一個表中的列將包含空值。如果表之間有匹配行,則整個結果集的行包含基表的數據。

本文鏈接http://www.cnblogs.com/hanzongze/p/oracle-sql-rows.html
版權聲明:本文為博客園博主 韓宗澤 原創,作者保留署名權!歡迎通過轉載、演繹或其它傳播方式來使用本文,但必須在明顯位置給出作者署名和本文鏈接!個人博客,能力有限,若有不當之處,敬請批評指正,謝謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...