Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

Gộp hàng (Merge rows) trong MySQL?

Gộp nhiều hàng thành một hàng với GROUP_CONCAT() trong MySQL

Hàm GROUP_CONCAT() nối chuỗi các giá trị trong nhóm (GROUP BY) thành một chuỗi, phân cách bằng dấu phân cách tùy chọn. Dùng để "gộp hàng" theo khóa chung.

Ví dụ minh họa

Tạo bảng DemoTable734:

mysql> CREATE TABLE DemoTable734 (
    Id INT,
    Name VARCHAR(100)
);
Query OK, 0 rows affected (0.73 sec)

Chèn dữ liệu (Name trùng lặp, Id khác nhau):

mysql> INSERT INTO DemoTable734 VALUES(101, 'John');
Query OK, 1 row affected (0.23 sec)
mysql> INSERT INTO DemoTable734 VALUES(102, 'John');
Query OK, 1 row affected (0.22 sec)
mysql> INSERT INTO DemoTable734 VALUES(103, 'Chris');
Query OK, 1 row affected (0.14 sec)
mysql> INSERT INTO DemoTable734 VALUES(104, 'Chris');
Query OK, 1 row affected (0.20 sec)
mysql> INSERT INTO DemoTable734 VALUES(104, 'Chris');
Query OK, 1 row affected (0.13 sec)

Xem dữ liệu gốc (5 hàng):

mysql> SELECT * FROM DemoTable734;
+------+-------+
| Id   | Name  |
+------+-------+
| 101  | John  |
| 102  | John  |
| 103  | Chris |
| 104  | Chris |
| 104  | Chris |
+------+-------+
5 rows in set (0.00 sec)

Gộp theo Name, nối Id distinct bằng dấu phẩy:

mysql> SELECT Name, GROUP_CONCAT(DISTINCT Id SEPARATOR ',') FROM DemoTable734 GROUP BY Name;

Kết quả (2 hàng, Id đã gộp):

+-------+-----------------------------------------+
| Name  | GROUP_CONCAT(DISTINCT Id SEPARATOR ',') |
+-------+-----------------------------------------+
| Chris | 103,104                                 |
| John  | 101,102                                 |
+-------+-----------------------------------------+
2 rows in set (0.04 sec)

Các tùy chọn GROUP_CONCAT

Tùy chọnCú phápMặc định
Phân cáchSEPARATOR ','','
Loại trùngDISTINCTGiữ trùng (ALL)
Sắp xếp trong nhómORDER BY Id ASCThứ tự không xác định
Giới hạn độ dàigroup_concat_max_len (system var)1024 bytes

Ví dụ đầy đủ tùy chọn

SELECT 
    Name,
    GROUP_CONCAT(DISTINCT Id ORDER BY Id ASC SEPARATOR '; ') AS Ids
FROM DemoTable734 
GROUP BY Name;

Tăng giới hạn độ dài kết quả

-- Session level
SET SESSION group_concat_max_len = 1000000;

-- Global (cần SUPER privilege, persistent qua restart cần config file)
SET GLOBAL group_concat_max_len = 1000000;

Ứng dụng thực tế

  • Danh sách tag/categories của bài viết: GROUP_CONCAT(tag_name)
  • Email nhận CC: GROUP_CONCAT(email SEPARATOR ';')
  • JSON array thủ công: CONCAT('[', GROUP_CONCAT(JSON_OBJECT('id', id, 'name', name)), ']')
  • Pivot ngược (rows → columns) kết hợp CASE WHEN

Lưu ý

  • Kết quả bị cắt nếu vượt group_concat_max_len (mặc định 1024 bytes)
  • DISTINCT tăng chi phí CPU/bộ nhớ
  • MySQL 8.0+: cân nhắc JSON_ARRAYAGG() cho output JSON chuẩn