如何使用 SQL INNER JOIN 聯結兩個或多個表

来源:https://www.cnblogs.com/vin-c/archive/2022/05/17/16279509.html
-Advertisement-
Play Games

本文介紹什麼是 SQL INNER JOIN 聯結,為什麼使用聯結,如何編寫使用聯結的 SELECT 語句。並講述了一些關係資料庫設計的基本知識,包括等值聯結(也稱為內聯結)這種最常用的聯結。 一、聯結 SQL 最強大的功能之一就是能在數據查詢的執行中聯結(join)表。聯結是利用 SQL 的 SE ...


目錄

本文介紹什麼是 SQL INNER JOIN 聯結,為什麼使用聯結,如何編寫使用聯結的 SELECT 語句。並講述了一些關係資料庫設計的基本知識,包括等值聯結(也稱為內聯結)這種最常用的聯結。

一、聯結

SQL 最強大的功能之一就是能在數據查詢的執行中聯結(join)表。聯結是利用 SQL 的 SELECT 能執行的最重要的操作,很好地理解聯結及其語法是學習 SQL 的極為重要的部分。

在能夠有效地使用聯結前,必須瞭解關係表以及關係資料庫設計的一些基礎知識。下麵的介紹並不能涵蓋這一主題的所有內容,但作為入門已經夠了。

1.1 關係表

理解關係表,最好是來看個例子。

有一個包含產品目錄的資料庫表,其中每類物品占一行。對於每一種物品,要存儲的信息包括產品描述、價格,以及生產該產品的供應商。

現在有同一供應商生產的多種物品,那麼在何處存儲供應商名、地址、聯繫方法等供應商信息呢?將這些數據與產品信息分開存儲的理由是:

  • 同一供應商生產的每個產品,其供應商信息都是相同的,對每個產品重覆此信息既浪費時間又浪費存儲空間;
  • 如果供應商信息發生變化,例如供應商遷址或電話號碼變動,只需修改一次即可;
  • 如果有重覆數據(即每種產品都存儲供應商信息),則很難保證每次輸入該數據的方式都相同。不一致的數據在報表中就很難利用。

關鍵是,相同的數據出現多次決不是一件好事,這是關係資料庫設計的基礎。

關係表的設計就是要把信息分解成多個表,一類數據一個表。各表通過某些共同的值互相關聯(所以才叫關係資料庫)。

在這個例子中可建立兩個表:一個存儲供應商信息,另一個存儲產品信息。Vendors 表包含所有供應商信息,每個供應商占一行,具有唯一的標識。

此標識稱為主鍵(primary key),可以是供應商 ID 或任何其他唯一值。

Products 表只存儲產品信息,除了存儲供應商 IDVendors 表的主鍵)外,它不存儲其他有關供應商的信息。

Vendors 表的主鍵將 Vendors 表與 Products 表關聯,利用供應商 ID 能從 Vendors 表中找出相應供應商的詳細信息。

這樣做的好處是:

  • 供應商信息不重覆,不會浪費時間和空間;
  • 如果供應商信息變動,可以只更新 Vendors 表中的單個記錄,相關表中的數據不用改動;
  • 由於數據不重覆,數據顯然是一致的,使得處理數據和生成報表更簡單。

總之,關係數據可以有效地存儲,方便地處理。因此,關係資料庫的可伸縮性遠比非關係資料庫要好。

可伸縮(scale)

能夠適應不斷增加的工作量而不失敗。設計良好的資料庫或應用程式稱為可伸縮性好(scale well)。

1.2 為什麼使用聯結

如前所述,將數據分解為多個表能更有效地存儲,更方便地處理,並且可伸縮性更好。但這些好處是有代價的。

如果數據存儲在多個表中,怎樣用一條 SELECT 語句就檢索出數據呢?

答案是使用聯結。簡單說,聯結是一種機制,用來在一條 SELECT 語句中關聯表,因此稱為聯結。使用特殊的語法,可以聯結多個表返回一組輸出,聯結在運行時關聯表中正確的行。

說明:使用互動式 DBMS 工具

重要的是,要理解聯結不是物理實體。換句話說,它在實際的資料庫表中並不存在。DBMS 會根據需要建立聯結,它在查詢執行期間一直存在。

許多 DBMS 提供圖形界面,用來互動式地定義表關係。這些工具極其有助於維護引用完整性。在使用關係表時,僅在關係列中插入合法數據是非常重要的。

回到這裡的例子,如果 Products 表中存儲了無效的供應商 ID,則相應的產品不可訪問,因為它們沒有關聯到某個供應商。

為避免這種情況發生,可指示資料庫只允許在 Products 表的供應商 ID 列中出現合法值(即出現在 Vendors 表中的供應商)。

引用完整性表示 DBMS 強制實施數據完整性規則。這些規則一般由提供了界面的 DBMS 管理。

二、創建聯結

創建聯結非常簡單,指定要聯結的所有表以及關聯它們的方式即可。請看下麵的例子:

SELECT vend_name, prod_name, prod_price
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;

輸出:

vend_name                prod_name                prod_price
--------------------     --------------------     ----------
Doll House Inc.          Fish bean bag toy        3.4900
Doll House Inc.          Bird bean bag toy        3.4900
Doll House Inc.          Rabbit bean bag toy      3.4900
Bears R Us               8 inch teddy bear        5.9900
Bears R Us               12 inch teddy bear       8.9900
Bears R Us               18 inch teddy bear       11.9900
Doll House Inc.          Raggedy Ann              4.9900
Fun and Games            King doll                9.4900
Fun and Games            Queen doll               9.4900

我們來看這段代碼。

SELECT 語句與前面所有語句一樣指定要檢索的列。這裡最大的差別是所指定的兩列(prod_nameprod_price)在一個表中,而第一列(vend_name)在另一個表中。

現在來看 FROM 子句。

與以前的 SELECT 語句不一樣,這條語句的 FROM 子句列出了兩個表:VendorsProducts

它們就是這條 SELECT 語句聯結的兩個表的名字。這兩個表用 WHERE 子句正確地聯結,WHERE 子句指示 DBMS 將 Vendors 表中的 vend_idProducts 表中的 vend_id 匹配起來。

可以看到,要匹配的兩列指定為 Vendors.vend_idProducts.vend_id。這裡需要這種完全限定列名,如果只給出 vend_id,DBMS 就不知道指的是哪一個(每個表中有一個)。

從前面的輸出可以看到,一條 SELECT 語句返回了兩個不同表中的數據。

警告:完全限定列名

就像 如何在 SQL 中使用子查詢 提到的,在引用的列可能出現歧義時,必須使用完全限定列名(用一個句點分隔表名和列名)。

如果引用一個沒有用表名限制的具有歧義的列名,大多數 DBMS 會返回錯誤。

2.1 WHERE 子句的重要性

使用 WHERE 子句建立聯結關係似乎有點奇怪,但實際上是有個很充分的理由的。

要記住,在一條 SELECT 語句中聯結幾個表時,相應的關係是在運行中構造的。在資料庫表的定義中沒有指示 DBMS 如何對錶進行聯結的內容。你必須自己做這件事情。

在聯結兩個表時,實際要做的是將第一個表中的每一行與第二個表中的每一行配對。

WHERE 子句作為過濾條件,只包含那些匹配給定條件(這裡是聯結條件)的行。沒有 WHERE 子句,第一個表中的每一行將與第二個表中的每一行配對,而不管它們邏輯上是否能配在一起。

笛卡兒積(cartesian product)

由沒有聯結條件的表關係返回的結果為笛卡兒積。檢索出的行的數目將是第一個表中的行數乘以第二個表中的行數。

理解這一點,請看下麵的 SELECT 語句及其輸出:

SELECT vend_name, prod_name, prod_price
FROM Vendors, Products;

輸出:

vend_name           prod_name                       prod_price
----------------    ----------------------------    ----------
Bears R Us          8 inch teddy bear               5.99
Bears R Us          12 inch teddy bear              8.99
Bears R Us          18 inch teddy bear              11.99
Bears R Us          Fish bean bag toy               3.49
Bears R Us          Bird bean bag toy               3.49
Bears R Us          Rabbit bean bag toy             3.49
Bears R Us          Raggedy Ann                     4.99
Bears R Us          King doll                       9.49
Bears R Us          Queen doll                      9.49
Bear Emporium       8 inch teddy bear               5.99
Bear Emporium       12 inch teddy bear              8.99
Bear Emporium       18 inch teddy bear              11.99
Bear Emporium       Fish bean bag toy               3.49
Bear Emporium       Bird bean bag toy               3.49
Bear Emporium       Rabbit bean bag toy             3.49
Bear Emporium       Raggedy Ann                     4.99
Bear Emporium       King doll                       9.49
Bear Emporium       Queen doll                      9.49
Doll House Inc.     8 inch teddy bear               5.99
Doll House Inc.     12 inch teddy bear              8.99
Doll House Inc.     18 inch teddy bear              11.99
Doll House Inc.     Fish bean bag toy               3.49
Doll House Inc.     Bird bean bag toy               3.49
Doll House Inc.     Rabbit bean bag toy             3.49
Doll House Inc.     Raggedy Ann                     4.99
Doll House Inc.     King doll                       9.49
Doll House Inc.     Queen doll                      9.49
Furball Inc.        8 inch teddy bear               5.99
Furball Inc.        12 inch teddy bear              8.99
Furball Inc.        18 inch teddy bear              11.99
Furball Inc.        Fish bean bag toy               3.49
Furball Inc.        Bird bean bag toy               3.49
Furball Inc.        Rabbit bean bag toy             3.49
Furball Inc.        Raggedy Ann                     4.99
Furball Inc.        King doll                       9.49
Furball Inc.        Queen doll                      9.49
Fun and Games       8 inch teddy bear               5.99
Fun and Games       12 inch teddy bear              8.99
Fun and Games       18 inch teddy bear              11.99
Fun and Games       Fish bean bag toy               3.49
Fun and Games       Bird bean bag toy               3.49
Fun and Games       Rabbit bean bag toy             3.49
Fun and Games       Raggedy Ann                     4.99
Fun and Games       King doll                       9.49
Fun and Games       Queen doll                      9.49
Jouets et ours      8 inch teddy bear               5.99
Jouets et ours      12 inch teddy bear              8.99
Jouets et ours      18 inch teddy bear              11.99
Jouets et ours      Fish bean bag toy               3.49
Jouets et ours      Bird bean bag toy               3.49
Jouets et ours      Rabbit bean bag toy             3.49
Jouets et ours      Raggedy Ann                     4.99
Jouets et ours      King doll                       9.49
Jouets et ours      Queen doll                      9.49

從上面的輸出可以看到,相應的笛卡兒積不是我們想要的。這裡返回的數據用每個供應商匹配了每個產品,包括了供應商不正確的產品(即使供應商根本就沒有產品)。

註意:不要忘了 WHERE 子句

要保證所有聯結都有 WHERE 子句,否則 DBMS 將返回比想要的數據多得多的數據。

同理,要保證 WHERE 子句的正確性。不正確的過濾條件會導致 DBMS 返回不正確的數據。

提示:叉聯結

有時,返回笛卡兒積的聯結,也稱叉聯結(cross join)。

2.2 內聯結

目前為止使用的聯結稱為等值聯結(equijoin),它基於兩個表之間的相等測試。這種聯結也稱為內聯結(inner join)。其實,可以對這種聯結使用稍微不同的語法,明確指定聯結的類型。

下麵的 SELECT 語句返回與前面例子完全相同的數據:

SELECT vend_name, prod_name, prod_price
FROM Vendors
INNER JOIN Products ON Vendors.vend_id = Products.vend_id;

此語句中的 SELECT 與前面的 SELECT 語句相同,但 FROM 子句不同。

這裡,兩個表之間的關係是以 INNER JOIN 指定的部分 FROM 子句。

在使用這種語法時,聯結條件用特定的 ON 子句而不是 WHERE 子句給出。傳遞給 ON 的實際條件與傳遞給 WHERE 的相同。

至於選用哪種語法,請參閱具體的 DBMS 文檔。

說明:“正確的”語法

ANSI SQL 規範首選 INNER JOIN 語法,之前使用的是簡單的等值語法。

其實,SQL 語言純正論者是用鄙視的眼光看待簡單語法的。

這就是說,DBMS 的確支持簡單格式和標準格式,我建議你要理解這兩種格式,具體使用就看你用哪個更順手了。

2.3 聯結多個表

SQL 不限制一條 SELECT 語句中可以聯結的表的數目。創建聯結的基本規則也相同。首先列出所有表,然後定義表之間的關係。例如:

SELECT prod_name, vend_name, prod_price, quantity
FROM OrderItems, Products, Vendors
WHERE Products.vend_id = Vendors.vend_id
 AND OrderItems.prod_id = Products.prod_id
 AND order_num = 20007;

輸出:

prod_name           vend_name         prod_price     quantity
---------------     -------------     ----------     --------
18 inch teddy bear  Bears R Us        11.9900        50
Fish bean bag toy   Doll House Inc.   3.4900         100
Bird bean bag toy   Doll House Inc.   3.4900         100
Rabbit bean bag toy Doll House Inc.   3.4900         100
Raggedy Ann         Doll House Inc.   4.9900         50

這個例子顯示訂單 20007 中的物品。訂單物品存儲在 OrderItems 表中。每個產品按其產品 ID 存儲,它引用 Products 表中的產品。

這些產品通過供應商 ID 聯結到 Vendors 表中相應的供應商,供應商 ID 存儲在每個產品的記錄中。

這裡的 FROM 子句列出三個表,WHERE 子句定義這兩個聯結條件,而第三個聯結條件用來過濾出訂單 20007 中的物品。

註意:性能考慮

DBMS 在運行時關聯指定的每個表,以處理聯結。這種處理可能非常耗費資源,因此應該註意,不要聯結不必要的表。聯結的表越多,性能下降越厲害。

註意:聯結中表的最大數目

雖然 SQL 本身不限制每個聯結約束中表的數目,但實際上許多 DBMS 都有限制。請參閱具體的 DBMS 文檔以瞭解其限制。

現在回顧一下 如何在 SQL 中使用子查詢 中的例子,如下的 SELECT 語句返回訂購產品 RGAN01 的顧客列表:

SELECT cust_name, cust_contact
FROM Customers
WHERE cust_id IN (SELECT cust_id
                  FROM Orders
                  WHERE order_num IN (SELECT order_num
                                      FROM OrderItems
                                      WHERE prod_id = 'RGAN01'));

如何在 SQL 中使用子查詢 所述,子查詢並不總是執行複雜 SELECT 操作的最有效方法,下麵是使用聯結的相同查詢:

SELECT cust_name, cust_contact
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id
 AND OrderItems.order_num = Orders.order_num
 AND prod_id = 'RGAN01';

輸出:

cust_name                         cust_contact
-----------------------------     --------------------
Fun4All                           Denise L. Stephens
The Toy Store                     Kim Howard

如何在 SQL 中使用子查詢 所述,這個查詢中的返回數據需要使用 3 個表。

但在這裡,我們沒有在嵌套子查詢中使用它們,而是使用了兩個聯結來連接表。這裡有三個 WHERE 子句條件。前兩個關聯聯結中的表,後一個過濾產品 RGAN01 的數據。

提示:多做實驗

可以看到,執行任一給定的 SQL 操作一般不止一種方法。很少有絕對正確或絕對錯誤的方法。

性能可能會受操作類型、所使用的 DBMS、表中數據量、是否存在索引或鍵等條件的影響。

因此,有必要試驗不同的選擇機制,找出最適合具體情況的方法。

說明:聯結的列名

上述所有例子里,聯結的幾個列的名字都是一樣的(例如 CustomersOrders 表裡的列都叫 cust_id)。

列名相同並不是必需的,而且你經常會遇到命名規範不同的資料庫。我這樣建表只是為了簡單起見。

三、小結

聯結是 SQL 中一個最重要、最強大的特性,有效地使用聯結需要對關係資料庫設計有基本的瞭解。

本文在介紹聯結時,講述了一些關係資料庫設計的基本知識,包括等值聯結(也稱為內聯結)這種最常用的聯結。

SQL 如何使用自聯結、自然聯結和外聯結 介紹如何創建其他類型的聯結。

原文鏈接:https://www.developerastrid.com/sql/sql-inner-join/

(完)


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

-Advertisement-
Play Games
更多相關文章
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 1.下載WSL Ubuntu 打開微軟商店,搜索linux,找到Ubuntu並下載 2.安裝WSL Ubuntu 下載完成以後先不要安裝,因為預設安裝位置是在c盤,此時在其他盤新建一個文件夾,打開C:\Program Files\WindowsA ...
  • 前言: 這是《VMware 虛擬機圖文安裝和配置 Rocky Linux 8.5 教程》一文的姐妹篇教程,如果你需要閱讀它,請點擊這裡。 2020 年,CentOS 宣佈:計劃未來將重心從 CentOS Linux 轉移到 CentOS Stream。CentOS 8 的生命周期已於 2021 年 ...
  • 1. mysql排序問題 一直以為mysql是按照主鍵排序的,實則排序和主鍵沒有關係(不使用 order by 子句)。 然後從 stackoverflow 上查了一下,找到了以下的回答: 沒有預設的排序順序。即使表具有聚集索引,也不能保證按該順序獲得結果。如果需要特定的順序,則必須使用ORDER ...
  • 一、概述 Presto是Facebook開源的MPP(Massively Parallel Processing:大規模並行處理)架構的OLAP(on-line transaction processing:聯機事務處理),完全基於記憶體的並⾏計算,可針對不同數據源,執行大容量數據集的一款分散式SQL ...
  • 書名《MySQL是怎樣運行的:從根兒上理解MySQL》。 這本書講得真的很好,建議大家想學習的去看看😊 本文是基於我的認識上將InnoDB的結構進行的回想,查缺補漏。 InnoDB記錄結構 InnoDB是以頁來存儲數據的,一個頁的大小為16KB。 InnoDB行格式有COMPACT行格式和Redu ...
  • 書名《MySQL是怎樣運行的:從根兒上理解MySQL》可自行百度 以下是知識點總結 重新認識Mysql MySQL是一個C/S架構的軟體。 在Windows安裝後首先註冊成服務,然後會在開機後自啟動。 啟動MySQL服務端。 直接在bin目錄下執行mysqld 或者在配置文件my.ini中設置一些默 ...
  • 導讀: 電商場景的搜索排序演算法根據用戶搜索請求,經過召回、粗排、精排、重排與混排等模塊將最終的結果呈現給用戶,演算法的優化目標是提升用戶轉化。傳統的有監督訓練方式,每一步迭代的過程中優化當前排序結果的即時反饋收益。但是,實際上用戶和搜索系統之間不斷交互,用戶狀態也在不斷變化,每一次交互後排序結果和用戶 ...
  • 查看PostgreSQL鎖表信息 一、查詢PG_STAT_ACTIVITY的信息 SELECT * FROM pg_stat_activity where datname='bms' and wait_event_type='Lock' 二、通過pid解鎖死鎖信息 select pg_cancel_ ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...