在學跨表單查詢之前,先來想一想:如果沒有電腦,你會怎麼把兩張表的資料合在一起?
當我們想清楚「手動會怎麼做」,就能更容易理解要給電腦什麼規則。
先來看一個情境
假設我們有兩張表:
會員表
| 會員 ID | 姓名 | 電話 | 信箱 |
|---|---|---|---|
| 1 | John | 0912-xxx | john@mail.com |
| 2 | Mary | 0923-xxx | mary@mail.com |
| 3 | Tom | 0934-xxx | tom@mail.com |
訂單表
| 訂單 ID | 會員 ID | 金額 |
|---|---|---|
| 1 | 1 | 60,000 |
| 2 | 1 | 20,000 |
| 3 | 2 | 55,000 |
為什麼訂單表裡面放的是「會員 ID」而不是「姓名」?
因為姓名、電話、信箱都可能會改,但 ID 不會變。
如果訂單表裡存的是「John」這個名字,哪天 John 改名了,你就要去改所有訂單的資料。
但如果存的是「會員 ID = 1」,不管 John 怎麼改名,訂單資料都不用動。
這就是我們在正規化時學到的原則:用不會變的 ID 來建立關聯。
先計算:先算出符合條件的 ID,再去另一張表找資料
假設老闆說:「幫我找出平均客單價 5 萬以上的會員,然後給我他們的信箱。」
你會怎麼做?
大多數人第一個想到的方法是:先從訂單表算出「誰符合條件」,拿到會員 ID 後,再去會員表查資料。
第一步:計算每個會員的平均客單價
先對訂單表做分組查詢,按「會員 ID」分組,然後計算每個會員的平均金額:
- 會員 1(John)有兩筆訂單:60,000 和 20,000,平均是 (60,000 + 20,000) ÷ 2 = 40,000
- 會員 2(Mary)只有一筆訂單:55,000,平均就是 55,000
結果如下:
| 會員 ID | 平均客單價(平均金額) |
|---|---|
| 1 | 40,000 |
| 2 | 55,000 |
第二步:篩選出符合條件的會員
平均客單價超過 5 萬的只有會員 ID = 2。
第三步:回去會員表查信箱
拿著「會員 ID = 2」這個條件,去會員表查詢。
查到 Mary,信箱是 mary@mail.com。
完成!
這個方法的優點
簡單暴力,容易理解。
你只要會「篩選」就能做到。
這個方法的缺點
當老闆接著問:「那這些超過 5 萬的會員,他們的平均客單價分別是多少?」
你會發現,你需要再回去翻一次剛剛的計算結果才能回答。
因為在反查的過程中,你只帶了「會員 ID」去會員表查信箱。
平均客單價這個資訊,並沒有一起帶過來。
如果今天符合條件的會員有 100 個,你就要來回對照兩張表,很麻煩。
先合併:把兩張表合成一張大表,再做計算
第二個方法是:把兩張表先合併成一張大表,再來做計算和篩選。
合併的邏輯
你可以想像成這樣:
「欸,會員 ID 是 1,那他的姓名是什麼?」
「John。」
「電話呢?」
「0912-xxx。」
就像你跟同事一來一往,把資料抄過來一樣。
合併的條件
兩張表要怎麼「對起來」?
靠的是會員 ID。
合併的邏輯是這樣:把會員表的「會員 ID」跟訂單表的「會員 ID」對在一起,只要兩邊的 ID 相同,就把資料接起來。
用白話講,合併的條件就是:
會員表.會員ID = 訂單表.會員ID
當我們用這個條件合併後,會得到這張大表:
你會發現 John 出現了兩次。
這是正常的!
因為 John 有兩筆訂單,所以合併後會變成兩列。
重點:一筆資料對應到多筆時,就會複製多列。
為什麼要寫出合併條件?
你可能覺得「用 ID 對起來」很直觀,幹嘛還要特別寫出來?
想像一下,如果你請同事幫你合併兩張表,你會怎麼說?
你不會只說「幫我把這兩張表合起來」,你會說「用會員 ID 對起來」。
因為如果不講清楚,同事可能會問:「要用哪個欄位對?」
而且,有時候兩邊的欄位名稱還不一樣。
例如會員表叫「ID」,訂單表叫「會員 ID」,這時候如果你不講清楚,同事根本不知道要怎麼對。
寫程式也是一樣,你要明確告訴它合併的依據是什麼。
合併時遇到「沒對應到」的資料怎麼辦?
你有沒有注意到,Tom 不見了?
因為 Tom 沒有任何訂單,所以在合併時「對不上」。
這時候你有兩個選擇:
選擇一:直接刪掉
Tom 沒買東西,不管他。
這在目前的任務是 OK 的,因為我們只要找「平均客單價 5 萬以上」的人。
選擇二:保留,補空值
有時候你需要看「所有會員」的分布,包含沒買東西的人。
這時候就要保留 Tom,然後在訂單的欄位補上空值(NULL)。
| 會員 ID | 姓名 | 電話 | 信箱 | 訂單 ID | 金額 |
|---|---|---|---|---|---|
| 1 | John | 0912-xxx | john@mail.com | 1 | 60,000 |
| 1 | John | 0912-xxx | john@mail.com | 2 | 20,000 |
| 2 | Mary | 0923-xxx | mary@mail.com | 3 | 55,000 |
| 3 | Tom | 0934-xxx | tom@mail.com | NULL | NULL |
之後再用其他方法(像是把 NULL 換成 0)來處理。
要刪掉還是保留,取決於你的任務需求。
回到老闆的任務:用合併後的大表來完成
現在我們有了這張合併後的大表,要怎麼找出「平均客單價 5 萬以上的會員信箱」?
第一步:計算每個會員的平均客單價
用「會員 ID」做分組,計算每個人的平均金額:
- John(會員 ID = 1):(60,000 + 20,000) ÷ 2 = 40,000
- Mary(會員 ID = 2):55,000 ÷ 1 = 55,000
分組計算後,表格會變成這樣:
| 會員 ID | 姓名 | 信箱 | 平均客單價 |
|---|---|---|---|
| 1 | John | john@mail.com | 40,000 |
| 2 | Mary | mary@mail.com | 55,000 |
第二步:篩選出平均客單價超過 5 萬的會員
只有 Mary 超過 5 萬。
第三步:拿到信箱
因為信箱就在同一張表裡,直接就能看到 Mary 的信箱是 mary@mail.com。
完成!
「先合併」的好處
你有發現嗎?用這個方法,所有資訊都在同一張表上。
如果老闆接著問:「那 Mary 的平均客單價是多少?」
你可以直接回答:55,000。
不用再回去翻另一張表,因為資料都在這裡了。
兩種做法的比較
| 項目 | 先計算 | 先合併 |
|---|---|---|
| 難度 | 簡單 | 稍微複雜 |
| 優點 | 直觀好懂 | 可以保留所有細節 |
| 缺點 | 會丟失另一張表的細節 | 合併後資料量會變大 |
| 適合情境 | 只需要最終結果 | 需要看到完整資料 |
先計算
優點是簡單好懂。
你先在訂單表算出結果,拿到符合條件的會員 ID,再把這個 ID 當成篩選條件,去會員表查資料。
整個過程就是「算一次 → 篩選一次」,邏輯很直線。
缺點是,當老闆追問細節時(例如平均客單價是多少),你要再回去查一次。
適合「只需要最終結果」的情境,例如老闆只要一份名單,不會追問。
先合併
這個方法是先把兩張表合成一張大表,再做計算和篩選。
優點是所有資訊都在同一張表上,老闆追問時不用再回去翻。
缺點是合併後資料量會變大,尤其是一對多的情況,同一筆資料會重複出現。
適合用在「需要看到完整資料」的情境,例如老闆可能會追問細節,或是你需要做進一步的分析。
實務上的建議
實務上,「先合併」的做法會比較常用,因為它能保留更多細節,後續要做什麼分析都方便。
但它有個小挑戰:合併後的表可能很長,不容易一眼看懂自己到底合出了什麼。
所以有個好習慣:先把合併的結果印出來看一下。
確認資料長相符合預期,再繼續做後面的計算。
這樣可以避免合錯了還不知道,一路錯到底。
小結
- 先計算:簡單暴力,但會丟失細節
- 先合併:保留完整資料,但需要明確寫出合併條件
- 一筆對多筆時,合併後會複製多列
- 沒對應到的資料,可以選擇刪掉或保留並補空值
- 合併條件不一定是「等於」,要根據需求來寫
下一篇文章,我們會先來看「先計算」的寫法,也就是把子查詢放在篩選條件中的做法。