一、問題場景與痛點
在數據庫設計中,經常會遇到統計某一些數據的最大數量最小數量等,特別是**逗號分隔字段 **的統計會顯得非常困難
下面以我生產上遇到的一個問題講解:
有個需求是在o_work_order表中統計sn字段中哪個工單號的數量最多,sn的存儲結構如下:“CF208RC1,CF208L11,CF208L11,CF208L11,…”:
- 傳統方案:需拆分字段為臨時表或使用JSON解析,代碼復雜且性能低下。
- 高效需求:直接計算分隔符數量,避免中間表生成。
二、核心公式解析:LENGTH() - LENGTH(REPLACE()) + 1
通過字符串長度差值計算元素數量,是最高效的純SQL方案:
SELECT order_id,LENGTH(sn) - LENGTH(REPLACE(sn, ',', '')) + 1 AS sn_count
FROM o_work_order
原理解析(以 sn='A,B,C'
為例):
步驟 | 表達式 | 示例值 | 說明 |
---|---|---|---|
1 | LENGTH(sn) | 5 | 原始字符串長度(含逗號) |
2 | REPLACE(sn, ',', '') | 'ABC' | 刪除所有逗號 |
3 | LENGTH(REPLACE(...)) | 3 | 無逗號字符串長度 |
4 | 差值 = 步驟1 - 步驟3 | 5 - 3 = 2 | 逗號個數 |
5 | sn_count = 差值 + 1 | 2 + 1 = 3 | 最終元素數量 |
? 優勢:
無需遞歸或子查詢,
性能提升10倍以上;
兼容MySQL 5.x至8.x所有版本。
三、優化技巧
-
過濾空值避免干擾
添加條件排除無效數據:WHERE sn IS NOT NULL AND sn != '' -- 忽略空字段
-
索引加速查詢
對高頻過濾字段創建聯合索引:CREATE INDEX idx_category_sn ON o_work_order(order_category, sn);
-
處理特殊格式
連續逗號
(如A,C):
先標準化格式:
REPLACE(REPLACE(sn, ',,', ','), ',,', ',') -- 遞歸替換連續逗號
結尾逗號(如A,B,):公式仍正確計數(結果為3),無需額外處理。
四、總結
最后的結果也是達到預期如下圖所示
核心公式本質:
??元素數量 = 分隔符數量 + 1??
通過字符串函數直接計算,避免復雜解析過程,是處理分隔字段的??性能最優解??。