首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL GROUP_CONCAT 實戰:一條 SQL 實現一對多數據聚合展示

     編輯:MySQL 綜合教學

業務場景

班級表 banji(id, class_name),學生表 user(id, name, class_id)。需求:查詢所有班級及其學生名單,**每班一行**,學生名以分隔符拼接。

核心語法

SELECT
    b.*,
    GROUP_CONCAT(u.name SEPARATOR '|') AS student_names
FROM banji b
LEFT JOIN user u ON b.id = u.class_id
WHERE b.id = 2
GROUP BY b.id;

結果對比

方案返回行數學生欄位
普通 JOIN學生數 N 行單個名字,重複班級信息
GROUP_CONCAT1 行lisi|zhaoliu|liu|小二|xiaoming|小張

進階用法

1. 自定義分隔符、排序、去重

GROUP_CONCAT(DISTINCT u.name ORDER BY u.name SEPARATOR ',')
  • DISTINCT:去重(防止髒數據重複)。
  • ORDER BY:組內排序,保證輸出確定性。
  • SEPARATOR:默認逗號,可改 |、;、\n 等。

2. 多欄位聚合 (JSON 格式更優)

SELECT
    b.id,
    b.class_name,
    GROUP_CONCAT(CONCAT(u.id, ':', u.name) ORDER BY u.id SEPARATOR ';') AS students
FROM banji b
LEFT JOIN user u ON b.id = u.class_id
GROUP BY b.id, b.class_name;

輸出:1:lisi;2:zhaoliu;3:liu,應用層 split(';') → split(':') 解析。

3. 配合 JSON_ARRAYAGG (MySQL 5.7.22+ / 8.0) 返回標準 JSON

SELECT
    b.id,
    b.class_name,
    JSON_ARRAYAGG(JSON_OBJECT('id', u.id, 'name', u.name) ORDER BY u.id) AS students
FROM banji b
LEFT JOIN user u ON b.id = u.class_id
GROUP BY b.id, b.class_name;

輸出:[{"id":1,"name":"lisi"},{"id":2,"name":"zhaoliu"}],前端直食,無需解析。

關鍵限制與調優

限制默認值調整方法影響
group_concat_max_len1024 字節SET SESSION group_concat_max_len = 102400;超長截斷,導致數據不全
max_allowed_packet4MB/64MBSET GLOBAL max_allowed_packet = 1G;結果包過大報錯

最佳實踐:會話級設置足夠大值,避免全局副作用。

性能考量

  • GROUP_CONCAT 需將分組內所有行拼接,**內存中構建字符串**,大分組 (如 10 萬用戶) 會佔用大量內存、CPU。
  • 索引優化:user(class_id, name) 覆蓋索引,避免回表。
  • 超大聚合建議:應用層分批查詢、或異步預計算存入緩存/物化視圖。

跨數據庫對比

數據庫聚合函數備註
MySQLGROUP_CONCAT / JSON_ARRAYAGG最靈活
PostgreSQLSTRING_AGG / JSONB_AGG功能對標
OracleLISTAGG / WM_CONCAT (需安裝包)WM_CONCAT 非標準
SQL ServerSTRING_AGG (2017+) / FOR XML PATH舊版繞道 XML

實戰模板:標籤聚合

-- 文章標籤聚合
SELECT
    a.id,
    a.title,
    GROUP_CONCAT(t.name ORDER BY t.name SEPARATOR ',') AS tags
FROM article a
LEFT JOIN article_tag at ON a.id = at.article_id
LEFT JOIN tag t ON at.tag_id = t.id
GROUP BY a.id, a.title;

掌握 GROUP_CONCAT 及其現代替代者 JSON_ARRAYAGG,讓一對多查詢結果直接服務於 API 響應,減少應用層 N+1 查詢與拼接邏輯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved