🧾SQL 資料補值與跨表比對教學:用「同一筆主鍵」把錯誤欄位修正(新手也能懂)
你是不是也遇過這種情況:
資料表裡某個欄位的值「看起來怪怪的」,例如出現特殊符號、固定字母代碼、或明顯不是正常值;但你又知道「同一筆資料」在別的紀錄或別張表裡其實有正確值。這篇文章會用最白話的方式,帶你理解:
-
什麼是「用另一筆資料的欄位來補值」
-
為什麼你原本的查詢會「查不到(印出為空)」
-
如何用 SQL 寫出「只取第一筆」的補值規則
-
如何安全地把 SELECT 改成 UPDATE
-
如何比對兩張表中「同一個主鍵」的資料是否一致
一、問題場景:資料欄位出現「非正常值」,需要用參考資料補回來
假設你有一張「測試記錄表」TestRecord,裡面有一個欄位
CodeTag(類似日期碼 / 批號碼 /
分類碼)。
但某些資料的
CodeTag
會出現異常值,例如包含特殊符號或固定字樣(這通常代表上游流程寫入失敗或
placeholder 值)。
你希望做到:
-
如果
CodeTag是異常值
→ 用同一批資料下「其他站點/其他流程」的正常CodeTag來取代 -
如果能取代的資料有多筆
→ 只拿「第一筆」作為參考(避免多筆造成更新不確定性)
二、為什麼你查詢會「印出為空」?新手最容易踩到的坑
很多人一開始會把條件寫得很精準,例如同時要求:
-
批號相同(例如
BatchNo) -
檔名相同(例如
FileName) -
且不是同一種站點(例如
Station <> 'X')
看起來合理,但實務上常常是:同一批資料在不同站點產生的檔名不會一樣。
所以你加上「檔名必須一樣」後,參考資料根本配不到,結果就會:
-
SELECT查不到 → 顯示空 -
UPDATE更新不到 → 影響筆數為 0
工程師思維:
先放寬條件驗證「資料是否存在」,再逐步加回規則。
三、正確做法:先找出「可被補值」的資料,再選一筆參考資料
1) 教學版:先用 SELECT 預覽「舊值」與「新值」
以下示範:當來源資料(a)的
CodeTag 出現異常(例如包含
# 或
TMP)時,用同批號(BatchNo)底下的參考資料(b)的
CodeTag 取代。
並且:如果參考資料有多筆,只取第一筆。
SELECT
a.RecordId,
a.BatchNo,
a.Station AS SourceStation,
a.CodeTag AS OldCodeTag,
ref.NewCodeTag
FROM TestRecord a
CROSS APPLY (
SELECT TOP (1)
b.CodeTag AS NewCodeTag
FROM TestRecord b
WHERE b.BatchNo = a.BatchNo
AND b.Station <> a.Station
AND b.CodeTag IS NOT NULL
AND b.CodeTag NOT LIKE '%#%'
AND b.CodeTag NOT LIKE '%TMP%'
ORDER BY b.CreatedAt ASC
) ref
WHERE a.Station = 'StationA'
AND (a.CodeTag LIKE '%#%' OR a.CodeTag LIKE '%TMP%');
你會看到:
-
OldCodeTag:原本異常的值 -
NewCodeTag:準備拿來補回去的值
重要觀念:先 SELECT 預覽,確認邏輯正確,再做 UPDATE。
四、把 SELECT 改成 UPDATE:安全地批次修正資料
當你確認上面的 SELECT 真的能找得到
NewCodeTag,接著就可以做
UPDATE。
UPDATE a
SET a.CodeTag = ref.NewCodeTag
FROM TestRecord a
CROSS APPLY (
SELECT TOP (1)
b.CodeTag AS NewCodeTag
FROM TestRecord b
WHERE b.BatchNo = a.BatchNo
AND b.Station <> a.Station
AND b.CodeTag IS NOT NULL
AND b.CodeTag NOT LIKE '%#%'
AND b.CodeTag NOT LIKE '%TMP%'
ORDER BY b.CreatedAt ASC
) ref
WHERE a.Station = 'StationA'
AND (a.CodeTag LIKE '%#%' OR a.CodeTag LIKE '%TMP%');
為什麼要用
CROSS APPLY + TOP 1?
因為你可能同一個批號會對到很多筆參考資料。
如果你用一般 JOIN 直接 UPDATE,可能會遇到:
-
更新結果不穩定(因為對到多筆)
-
甚至直接報錯(因 DB 引擎無法判定要用哪一筆)
CROSS APPLY + TOP 1
的價值就是:你明確告訴資料庫「只選一筆」。
五、你想用更簡單規則?只用「批號相同」也能補值
如果你發現「檔名相同」根本配不到,那就代表你的資料特性不適合用檔名當關聯條件。
此時你可以只靠「批號/工單號」這種真正能跨站點一致的欄位來補值。
上面教學版就是這個思路:以 BatchNo(或 MO)作為主關聯條件。
六、跨表比對:如何找出兩張表「主鍵一致」的資訊
另一個常見需求是:
你有兩張表,例如:
-
TestRecord:測試明細 -
LotInfo:批次/工單基本資料
你想把兩張表用同一個主鍵(例如
ObjectKey)串起來看。
1) 找出兩張表都有的資料(交集)
SELECT
t.ObjectKey,
t.BatchNo,
t.Station,
l.LotNo,
l.VendorLotNo
FROM TestRecord t
INNER JOIN LotInfo l
ON t.ObjectKey = l.ObjectKey;
2) 找出「測試表有、批次表沒有」的異常資料
SELECT t.ObjectKey
FROM TestRecord t
LEFT JOIN LotInfo l
ON t.ObjectKey = l.ObjectKey
WHERE l.ObjectKey IS NULL;
這類查法在資料工程/ETL 很重要,常用來抓:
-
上游漏寫
-
轉檔漏進
-
主鍵不一致
-
同步延遲
七、工程師必做:更新前的 3 個保護措施
-
先 SELECT 預覽新舊值(你才知道會改到什麼)
-
加上「只取第一筆」規則(避免多筆不確定)
-
有條件就用 CreatedAt / Id 做排序(比用字串排序更可靠)
另外,如果資料量大,記得讓關聯欄位有索引,例如
BatchNo、ObjectKey、CreatedAt,效能差很多。
結語:從「查不到」到「穩定更新」的核心心法
當你遇到資料補值需求時,最重要的不是 SQL 花俏,而是:
-
先理解資料真正一致的關聯鍵是什麼(通常是工單/批號/主鍵)
-
避免用不穩定欄位(例如檔名、顯示名稱)當關聯條件
-
多筆參考資料時,一定要明確定義「取哪一筆」(TOP 1 + ORDER BY)
如果你把這三件事做對,90% 的資料補值與跨表比對問題都能穩穩解掉。
留言
張貼留言