首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL GROUP_CONCAT 進階:組內排序與去重一行搞定

     編輯:MySQL 資料庫相關知識

前言:GROUP_CONCAT 不只是拼字串

許多開發者只知道 GROUP_CONCAT(col) 將分組內的值用逗號連接,卻忽略了它支援 ORDER BY、DISTINCT、SEPARATOR 等強大子句。本文以實例示範如何在聚合時直接完成組內排序與去重,省去應用層二次處理。

場景:學生多科成績,需按分數降序展示

假設表 t1:

+----------+-------+
| username | score |
+----------+-------+
| Alice    |  85   |
| Alice    |  92   |
| Bob      |  78   |
| Bob      |  78   |  -- 重複分數
| Bob      |  88   |
+----------+-------+

原始資料

核心語法

SELECT
    username,
    GROUP_CONCAT(DISTINCT score ORDER BY score DESC SEPARATOR ' | ') AS scores
FROM t1
GROUP BY username;

關鍵點:

  • DISTINCT:組內去重,Bob 的 78 只出現一次。
  • ORDER BY score DESC:組內降序,高分在前。
  • SEPARATOR ' | ':自定義分隔符,預設逗號。

執行結果

+----------+-----------------+
| username | scores          |
+----------+-----------------+
| Alice    | 92 | 85         |
| Bob      | 88 | 78         |
+----------+-----------------+

結果展示

進階技巧與限制

需求寫法注意
多欄位拼接GROUP_CONCAT(CONCAT(course, ':', score) ORDER BY score DESC)先 CONCAT 再聚合
超長結果被截斷調大 group_concat_max_len(預設 1024 位元組)
SET SESSION group_concat_max_len = 1000000;
需在查詢前設定,或改用應用層分頁聚合
NULL 值處理預設忽略 NULL;若需保留用 COALESCE(score, 'N/A')
配合窗口函數 (8.0+)GROUP_CONCAT(score) OVER (PARTITION BY username ORDER BY score DESC)不需 GROUP BY,保留明細行

效能提示

  • GROUP_CONCAT 需在記憶體中構建字串,大量資料易觸發 tmp_table_size 限制導致磁碟臨時表,影響效能。
  • 單表超過 10 萬行或單組超過 1 萬值時,建議改為應用層分批查詢組裝,或使用 JSON_ARRAYAGG(5.7+)輸出 JSON 陣列再由前端處理。
  • 索引優化:確保 GROUP BY 欄位與 ORDER BY 欄位有合適索引(如 INDEX idx_user_score (username, score DESC)),可避免 filesort。

善用 GROUP_CONCAT 的完整語法,能將「查詢+排序+去重+格式化」壓縮在單一 SQL 完成,減少網路傳輸與應用層代碼,是報表類查詢的利器。

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