問題
`meta_value` (VARCHAR/TEXT) 存數字字串,直接 `ORDER BY meta_value` 產生字典序:
1, 10, 11, 123, 1234, 2, 25, 253, 3 -- 錯誤順序
方法一:CAST 轉型 (標準 SQL)
ORDER BY CAST(meta_value AS DECIMAL)
- 支援整數、小數、負數
- **前提**:所有值皆可轉數字,否則報錯
- 可指定精度:`DECIMAL(19,4)`
方法二:ABS 絕對值函數 (MySQL 隱式轉換)
ORDER BY ABS(meta_value)
- MySQL 遇數學運算自動將字串轉數字
- 效能與 `CAST` 相近
- **副作用**:負數變正數,若需保留負號排序**不可用**
效能建議
- **最佳**:欄位定義為數值型 (`INT`/`DECIMAL`),從源頭解決
- **次佳**:建立**虛擬產生欄位** (MySQL 5.7+ `GENERATED ALWAYS AS (CAST(meta_value AS DECIMAL)) STORED`) 並加索引
- **臨時**:`CAST`/`ABS` 現場轉換,無索引支援,大量資料全表掃描
WordPress 實戰背景
外掛 `Ludou Simple Vote` 將票數存 `postmeta.meta_value` (LONGTEXT),需排行榜功能,採用 `CAST` 方案相容性最好。
結語
字串欄位數值排序:**`CAST(... AS DECIMAL)` 通用、語意明確**;`ABS()` 簡短但改變負數語意。長期應調整欄位型別或加虛擬欄位索引。