🧾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 個保護措施

  1. 先 SELECT 預覽新舊值(你才知道會改到什麼)

  2. 加上「只取第一筆」規則(避免多筆不確定)

  3. 有條件就用 CreatedAt / Id 做排序(比用字串排序更可靠)

另外,如果資料量大,記得讓關聯欄位有索引,例如 BatchNoObjectKeyCreatedAt,效能差很多。


結語:從「查不到」到「穩定更新」的核心心法

當你遇到資料補值需求時,最重要的不是 SQL 花俏,而是:

  • 先理解資料真正一致的關聯鍵是什麼(通常是工單/批號/主鍵)

  • 避免用不穩定欄位(例如檔名、顯示名稱)當關聯條件

  • 多筆參考資料時,一定要明確定義「取哪一筆」(TOP 1 + ORDER BY)

如果你把這三件事做對,90% 的資料補值與跨表比對問題都能穩穩解掉。

留言

這個網誌中的熱門文章

🔍Vue.js 專案錯誤排查:解決 numericFields is not defined 與合併儲存格邏輯最佳化

🖥️遠端桌面連線完整新手指南:Windows RDP、Chrome Remote Desktop、AnyDesk、TeamViewer 一次搞懂

🔎EF Core 連 Oracle 出現 ORA-00600 [kpp_concatq:2] 的完整排錯指南(含 EF Core ToString/CultureInfo 錯誤)