萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL GROUP_CONCAT 函數完全指南:從基礎語法到百萬級性能優化

GROUP_CONCAT 是 MySQL 聚合查詢的利器,能將分組內的多行值合併為單一字串,極大簡化了報表統計、標籤聚合等場景的開發。本文系統梳理語法細節、長度限制突破、實戰案例與避坑指南。

語法全景圖

GROUP_CONCAT([DISTINCT] expr [,expr ...]
    [ORDER BY {col_name | expr} [ASC | DESC]]
    [SEPARATOR str_val])

簡記版:GROUP_CONCAT([DISTINCT] 欄位 [ORDER BY 排序] [SEPARATOR '分隔符'])

突破 1024 字節預設限制

預設 group_concat_max_len=1024,超長字串會被截斷。兩種調整方式:

  • 會話級:SET SESSION group_concat_max_len=10240;(推薦,不影響其他連線)
  • 全域/配置檔:SET GLOBAL group_concat_max_len=10240; 或 my.cnf 加入 group_concat_max_len=10240

實戰案例:從基礎到進階

測試表 aa(id, name) 數據:

id | name
1  | 10
1  | 20
1  | 20
2  | 20
3  | 200
3  | 500

1. 預設逗號分隔

SELECT id, GROUP_CONCAT(name) FROM aa GROUP BY id;
-- 1 | 10,20,20
-- 2 | 20
-- 3 | 200,500

2. 自訂分隔符

SELECT id, GROUP_CONCAT(name SEPARATOR ';') FROM aa GROUP BY id;
-- 1 | 10;20;20

3. 去重

SELECT id, GROUP_CONCAT(DISTINCT name) FROM aa GROUP BY id;
-- 1 | 10,20

4. 分組內排序

SELECT id, GROUP_CONCAT(name ORDER BY name DESC) FROM aa GROUP BY id;
-- 1 | 20,20,10

複雜場景:多表關聯標籤聚合

景點-類型多對多關聯,需將類型名稱聚合:

SELECT s.id, s.name, 
       GROUP_CONCAT(stt.name SEPARATOR ',') AS TypeName
FROM scenics s
INNER JOIN scenics_type srt ON srt.scenicsId = s.id
INNER JOIN scenicstype stt ON stt.id = srt.typeId AND stt.deleted=0
GROUP BY s.id;

單條 SQL 替代應用層循環查詢,效能提升數量級。

避坑指南:兩大隱形殺手

1. 整數型隱式轉換陷阱

GROUP_CONCAT(int欄位) 返回二進制字節流而非字串,必須顯式轉型:

-- 錯誤:返回 byte[]
SELECT GROUP_CONCAT(id) FROM t_ip;

-- 正確:CAST 或 CONVERT
SELECT GROUP_CONCAT(CAST(id AS CHAR)) FROM t_dep;
SELECT GROUP_CONCAT(CONVERT(id, CHAR)) FROM t_dep;

2. 長度截斷風險

即使調大 group_concat_max_len,極端數據仍可能超限。建議:

  • 業務層預估最大長度,預留 2 倍緩衝
  • 超大聚合改用應用層分頁拼接或臨時表
  • 監控 SHOW STATUS LIKE 'Group_concat%'; 觀察實際截斷情況

效能優化建議

  • 僅聚合必要欄位,避免 GROUP_CONCAT(*)
  • 配合 WHERE 縮小掃描範圍
  • 大表聚合前先建立覆蓋索引
  • 考慮 MAX(length) 預檢查結果長度

善用 GROUP_CONCAT 能讓複雜聚合查詢化繁為簡,但必須敬畏其長度限制與類型轉換陷阱,才能在生產環境穩健落地。

copyright © 萬盛學電腦網 all rights reserved