業務需求:酒店列表按中文名拼音排序。MySQL 預設 utf8_general_ci 按字符編碼排序(非拼音),需顯式指定拼音規則。本文提供兩種方案,涵蓋「極簡通用」與「精確可控」兩類場景。
SELECT hotel_name FROM hotel_base ORDER BY CONVERT(hotel_name USING gbk) COLLATE gbk_chinese_ci;
gbk_chinese_ci 校對集,直接按拼音比較。SELECT hotel_id, hotel_name,
ELT(INTERVAL(CONV(HEX(LEFT(CONVERT(hotel_name USING gbk), 1)), 16, 10),
0xB0A1, 0xB0C5, 0xB2C1, 0xB4EE, 0xB6EA, 0xB7A2, 0xB8C1, 0xB9FE,
0xBBF7, 0xBFA6, 0xC0AC, 0xC2E8, 0xC4C3, 0xC5B6, 0xC5BE, 0xC6DA,
0xC8BB, 0xC8F6, 0xCBFA, 0xCDDA, 0xCEF4, 0xD1B9, 0xD4D1),
'A','B','C','D','E','F','G','H','J','K','L','M','N','O','P','Q','R','S','T','W','X','Y','Z') AS PY
FROM hotel_base
ORDER BY PY ASC;
CONVERT(... USING gbk) → 取首字節 GBK 編碼(雙字節)。LEFT(...,1) 取首字節高位,HEX 轉十六進制,CONV(...,16,10) 轉十進制數值。INTERVAL(val, boundary1, boundary2...) 判斷落在哪個拼音區間(GBK 漢字區 0xB0A1~0xD4D1 分 24 段)。ELT(index, 'A','B'...) 映射為首字母。py_initial CHAR(1)),排序直接走索引,極快;邏輯透明,可自定義多音字修正。| 方案 | 首次排序耗時 | 建立索引後排序 | 適用場景 |
|---|---|---|---|
| CONVERT+COLLATE | ~3.2 秒 | 不支援索引 | 中小表、臨時查詢、不想改結構 |
| HEX+ELT 首字母列+索引 | ~0.05 秒 | ~0.001 秒 | 大表、高頻排序、API 介面 |
py_initial CHAR(1) 列,寫入時觸發器/應用層按方案二邏輯填充,建立索引 INDEX idx_py (py_initial, hotel_name)。word, py_initial),方案一無法干預。ICU 校對集 utf8mb4_zh_0900_as_cs 等原生支援拼音排序,無需轉 GBK。按業務體量選型:「小表用隱式轉換,大表用顯式首字母索引」,兼顧開發速度與查詢性能。