跳到主要內容
DuckDB 2.0 實作:找出五千筆退款的重複列
/閱讀約 7 分鐘/

DuckDB 2.0 實作:找出五千筆退款的重複列

DuckDB 2.0 的 agent mode 會標明查詢輸出省略了多少列。本文用五千筆合成退款匯出資料,在本機重跑取樣、重複鍵檢查與分幣別加總,找出藏在中間的重複列;附可下載的資料與驗證程式,並說明同鍵金額衝突及整數解析的處理界線。

目錄+

五千筆退款匯出,終端畫面只有四十筆。這次本機重跑,把一筆重複資料放在中間:只看首尾取樣找不到它,完整查詢卻算出多了一千九百九十九元。想讓 AI 幫忙查資料,得先確認交給它的是完整答案,還是部分畫面。

DuckDB 在十月二十一日發布 2.0 正式版,CLI 的 agent mode 會明示輸出截斷。以下是 macOS 上的實際 SQL 與輸出格式重跑,使用官方二點零版;沒有呼叫語言模型,也沒有連接收款平台,不能據此宣稱模型更準或省下費用。

先準備可重跑的五千筆資料

下載合成資料與驗證程式,解壓後會得到 CSV、查詢與一支只用標準函式庫的 Python 程式。另從 DuckDB 官方版本頁取得適合系統的 CLI,再於解壓目錄執行:

python3 run-lab.py --duckdb /absolute/path/to/duckdb

程式會重新產生五千列合成退款,保存查詢的原始輸出,最後驗證筆數與金額。這份練習刻意讓第二千五百零一列重複前一列的退款 ID;訂單 ID、金額、幣別與狀態也相同,只有來源列號不同。它模擬重複匯出,沒有代表某個平台真的退款兩次。

金額欄位 amount_minor 使用整數分,本例幣別全為新臺幣,一百個最小單位等於一元。資料不含姓名、電子信箱或真實交易,重跑也不會寫入外部帳號。

四十筆畫面不能回答全表問題

在相同目錄對 CSV 執行預覽:

duckdb -init /dev/null -agent -c \
  "SELECT * FROM 'refunds.csv' ORDER BY source_row_no;"

本次輸出列出前二十與後二十筆,中間明寫省略四千九百六十列,結尾保留總列數與雜湊:

… 4960 rows omitted …
first 20 and last 20 of 5000 rows (.maxbytes 0 for all), hash a66ba0d297062869

依官方文件,agent mode 預設在一千列及一萬位元組的範圍內完整輸出,較大結果改顯示首尾。因此四十筆是這個大結果的取樣,不是所有查詢都只能印四十筆。第二千五百列的重複鍵沒有出現在這份取樣裡。

此時直接問「畫面裡有沒有重複」只能檢查這四十筆。接下來應讓資料庫查完整集合,再把小型結果交出去;把取樣貼給模型並不能補回省略的列。

先查重複鍵,再查同鍵是否衝突

下面這條查詢直接讀完整 CSV,以退款 ID 分組;同時核對相同 ID 有幾種有效資料內容:

SELECT refund_id, count(*) AS copies,
       count(DISTINCT (order_id, amount_minor, currency, status))
         AS payload_versions
FROM 'refunds.csv'
GROUP BY refund_id
HAVING count(*) > 1;

實際結果只有 rf_002500:出現兩列,內容版本數為一。這才能把它分類為本例中的重複匯出列。接著檢查所有 ID,是否有內容版本數大於一的情況;原始資料得到零筆衝突,才繼續加總。

下載包另附一個刻意設計的衝突測試:把第二千五百零一列的金額加一分,保持退款 ID 相同。重跑便得到一個衝突 ID。遇到這種資料要停下自動去重、查回來源,不可任選第一列,也不可因為 ID 相同就刪掉金額不同的紀錄。空白 ID、狀態變動或跨幣別資料,也需要先定義匯入規則。

加總前後,要對得上同一個差額

範例只加總成功狀態,先確認相同 ID 沒有衝突,再對退款 ID 與有效內容去重;保留來源列號會讓兩筆匯出仍被視為不同。完整 SQL 在下載包的 05-totals.sql,結果按幣別分開:

檢查項目本機結果
原始列數5,000
去重後退款數4,999
原始金額,單位為分65,373,800
去重後金額,單位為分65,173,900
重複部分,單位為分199,900

兩個總額相差一千九百九十九元,正好等於那筆重複匯出金額。不要用 SUM(DISTINCT amount_minor) 取代按退款 ID 去重;不同退款本來就可能有相同金額。另一個幣別也不能直接加進這張新臺幣表。聚合函式文件則提醒,空集合的加總會是 NULL,不能不加判斷地當成零。

真正卡住的是整數輸出解析

第一次驗證在 Python 的金額斷言失敗。本次 CLI 的 JSON 將 HUGEINT 加總輸出成字串 "199900",程式卻拿它和整數比較。修正方式是先確認字串只含合法整數,再用 int 解析;下載包已包含修正與檢查,沒有經過浮點數轉換。

這次完成的是固定資料的重複鍵查核與金額對照。agent mode 的完整列數、取樣標記與結果雜湊,能幫你判斷下一步該查什麼;它們不會替你決定退款規則。大量查詢若提前停止,列數可能只是下限,還得再縮小查詢。官方設計說明也公開了測量限制,不宜直接把輸出變短解讀成省錢。

準備把這段查核接進公司 Agent,可接著看兩週低風險試點,先把合成資料、成功條件與停止條件固定下來,再決定是否接正式來源。