跳至內容
Astera Technology

折扣明明是 15%,SQL 為甚麼計成零?

金額用整數分儲存時,百分比要先以小數計算,再按規則取整。

下載完整個案資料及參考答案 ↓

先準備用來排查的資料

例子以整數百分比計折扣,最後才用 SQLite ROUND 把非負金額取至最接近的一分。若先用整數除以 100,百分比的小數部分會被截去。只是改顯示格式,不能把已丟失的部分補回。

以下完整建表及資料只在新的 SQLite 測試資料庫執行。全部紀錄均為假設,數量以件計,輸入的 cents 金額欄以貨幣的分存整數;計算後的平均數可能不足整分。小型例子的各表均完整列在預覽。

假設輸入:offers
編號價格(分)折扣百分比
A1000015
B250000
下載可編輯 CSV ↓
可直接執行的完整測試資料
CREATE TABLE offers(id TEXT PRIMARY KEY,price_cents INTEGER,discount_pct INTEGER);
INSERT INTO offers VALUES ('A',10000,15),('B',25000,0);

重現錯誤結果,再核對更正

錯誤示範查詢:只用來重現問題
SELECT id,price_cents*(discount_pct/100) AS discount_cents FROM offers ORDER BY id;
實際執行的錯誤示範結果
編號折扣(分)
A0
B0
下載可編輯 CSV ↓
更正後的 SQLite 查詢
SELECT id,CAST(ROUND(price_cents*discount_pct/100.0,0) AS INTEGER) AS discount_cents FROM offers ORDER BY id;
更正查詢的實際結果
編號折扣(分)
A1500
B0
下載可編輯 CSV ↓

A 的 HK$100 方案打折 15%,折扣應是 1500 分;錯誤查詢卻是零。B 本來沒有折扣,兩個查詢都是零,說明只測零折扣會發現不到問題。

套用前先測邊界及資料範圍

99 分的項目折扣 50%,取整前是 49.5 分,本例變成 50 分。實際系統須確認這個邊界,不能假設所有取整規則相同。

邊界測試要另開新的假設資料庫,重做完整建表及資料,只套用以下改動,再執行更正查詢。測試改動不可用於正式系統。

新假設副本內的邊界改動
INSERT INTO offers VALUES ('C',99,50);
改動後再執行更正查詢的實際結果
編號折扣(分)
A1500
B0
C50
下載可編輯 CSV ↓

未計稅、負折扣、疊加優惠或多行合計取整;其他金額規則須另測。

以上錯誤、更正及邊界結果都已在 SQLite 執行,並與另行編寫的預期資料逐行核對。證據只適用於這組假設條件,未測其他資料庫、正式效能或你的現有資料結構。

相關資源