Trong MySQL, bạn có thể trả về kết quả truy vấn của mình dưới dạng danh sách được phân tách bằng dấu phẩy bằng cách sử dụng GROUP_CONCAT()
chức năng.
GROUP_CONCAT()
hàm được tạo riêng cho mục đích nối tập hợp kết quả của truy vấn vào một danh sách được phân tách bằng dấu phẩy hoặc dấu phân cách mà bạn chọn.
Bài viết này cung cấp các ví dụ về cách hoạt động của tất cả.
Dữ liệu
Trước tiên, hãy sử dụng dữ liệu sau trong một số ví dụ đầu tiên của chúng tôi:
USE Solutions; SELECT TaskName FROM Tasks;
Kết quả:
+-------------------+ | TaskName | +-------------------+ | Do garden | | Feed cats | | Paint roof | | Take dog for walk | | Relax | | Feed cats | +-------------------+
Ví dụ cơ bản
Đây là một ví dụ cơ bản để chứng minh GROUP_CONCAT()
chức năng:
SELECT GROUP_CONCAT(TaskName) FROM Tasks;
Kết quả:
+------------------------------------------------------------------+ | GROUP_CONCAT(TaskName) | +------------------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Take dog for walk,Relax,Feed cats | +------------------------------------------------------------------+
Như bạn có thể thấy, mỗi hàng từ tập hợp kết quả đã được nối thành một hàng duy nhất. Theo mặc định, danh sách được phân tách bằng dấu phẩy.
Lưu ý rằng có những hạn chế về thời gian danh sách này có thể dài. Tìm hiểu thêm về điều này ở phần sau của bài viết.
Ví dụ - DISTINCT
Bạn có thể sử dụng DISTINCT
để loại bỏ các bản sao (để các bản ghi trùng lặp trở thành một bản ghi).
Ví dụ:
SELECT GROUP_CONCAT(DISTINCT TaskName) FROM Tasks;
Kết quả:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName) | +--------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Relax,Take dog for walk | +--------------------------------------------------------+
Vì vậy, trong trường hợp này, "Cho mèo ăn" chỉ được liệt kê một lần, trong khi nó được liệt kê hai lần trong ví dụ trước.
Ví dụ - ĐẶT HÀNG THEO
Bạn có thể sử dụng ORDER BY
để sắp xếp các kết quả theo một cột nhất định.
Ví dụ:
SELECT GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) FROM Tasks;
Kết quả:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) | +--------------------------------------------------------+ | Take dog for walk,Relax,Paint roof,Feed cats,Do garden | +--------------------------------------------------------+
Vì vậy, trong trường hợp này, tôi sử dụng DESC
để xác định rằng nó phải theo thứ tự giảm dần. Giá trị thay thế (và mặc định) là ASC
để tăng dần.
Ví dụ - Chỉ định Dấu phân cách
Theo mặc định, danh sách là danh sách được phân tách bằng dấu phẩy. Tuy nhiên, bạn có thể chỉ định một dấu phân tách theo lựa chọn của mình nếu được yêu cầu.
Để thực hiện việc này, hãy sử dụng SEPARATOR
theo sau là giá trị ký tự của chuỗi sẽ được chèn vào giữa các giá trị của nhóm.
Ví dụ:
SELECT GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') FROM Tasks;
Kết quả:
+----------------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') | +----------------------------------------------------------------+ | Do garden + Feed cats + Paint roof + Relax + Take dog for walk | +----------------------------------------------------------------+
Ví dụ - Kết hợp các cột
Bạn cũng có thể nối các cột và cung cấp dấu phân tách của riêng chúng bằng cách cung cấp giá trị theo nghĩa đen của chuỗi.
Ví dụ:
SELECT GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') FROM Tasks;
Kết quả:
+------------------------------------------------------------------------------------+ | GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') | +------------------------------------------------------------------------------------+ | 1) Do garden 2) Feed cats 3) Paint roof 4) Take dog for walk 5) Relax 6) Feed cats | +------------------------------------------------------------------------------------+
Trong ví dụ này, chúng tôi trả về cả TaskId
và cột TaskName
, được phân tách bằng dấu ngoặc đơn và dấu cách. Chúng tôi cũng sử dụng SEPARATOR
đối số để chỉ định rằng dấu phân cách được sử dụng giữa mỗi hàng (được nối) phải là một khoảng trắng (thay vì dấu phẩy mặc định).
Kết quả được nhóm
GROUP_CONCAT()
hàm có thể hữu ích cho những trường hợp bạn muốn cung cấp danh sách kết quả, được nhóm theo một cột khác.
Ví dụ:bạn có thể muốn có một danh sách các nghệ sĩ, theo sau mỗi nghệ sĩ là danh sách các album họ đã phát hành.
Để chứng minh điều này, giả sử chúng ta có một cơ sở dữ liệu với hai bảng; Artists
và Albums
. Có một mối quan hệ một đến nhiều giữa các bảng này. Đối với mỗi nghệ sĩ, có thể có nhiều album.
Vì vậy, một truy vấn thông thường kết hợp cả hai bảng có thể trông giống như sau:
USE Music; SELECT ar.ArtistName, al.AlbumName FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId;
Kết quả:
+------------------------+--------------------------+ | ArtistName | AlbumName | +------------------------+--------------------------+ | Iron Maiden | Powerslave | | AC/DC | Powerage | | Jim Reeves | Singing Down the Lane | | Devin Townsend | Ziltoid the Omniscient | | Devin Townsend | Casualties of Cool | | Devin Townsend | Epicloud | | Iron Maiden | Somewhere in Time | | Iron Maiden | Piece of Mind | | Iron Maiden | Killers | | Iron Maiden | No Prayer for the Dying | | The Script | No Sound Without Silence | | Buddy Rich | Big Swing Face | | Michael Learns to Rock | Blue Night | | Michael Learns to Rock | Eternity | | Michael Learns to Rock | Scandinavia | | Tom Jones | Long Lost Suitcase | | Tom Jones | Praise and Blame | | Tom Jones | Along Came Jones | | Allan Holdsworth | All Night Wrong | | Allan Holdsworth | The Sixteen Men of Tain | +------------------------+--------------------------+
Như bạn có thể thấy, khi sử dụng định dạng này, nếu một nghệ sĩ có nhiều album, nghệ sĩ đó sẽ được liệt kê nhiều lần - một lần cho mỗi album.
Chúng tôi có thể sửa đổi truy vấn này để mỗi nghệ sĩ chỉ được liệt kê một lần. Nếu một nghệ sĩ có nhiều album, tất cả các album được hiển thị trong một trường duy nhất trong danh sách được phân tách bằng dấu phẩy. Chúng tôi có thể làm được điều này nhờ vào GROUP_CONCAT()
chức năng.
Ví dụ:
USE Music; SELECT ar.ArtistName, GROUP_CONCAT(al.AlbumName) FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId GROUP BY ArtistName;
Kết quả:
+------------------------+----------------------------------------------------------------------------+ | ArtistName | GROUP_CONCAT(al.AlbumName) | +------------------------+----------------------------------------------------------------------------+ | AC/DC | Powerage | | Allan Holdsworth | All Night Wrong,The Sixteen Men of Tain | | Buddy Rich | Big Swing Face | | Devin Townsend | Epicloud,Ziltoid the Omniscient,Casualties of Cool | | Iron Maiden | Somewhere in Time,Piece of Mind,Powerslave,Killers,No Prayer for the Dying | | Jim Reeves | Singing Down the Lane | | Michael Learns to Rock | Eternity,Scandinavia,Blue Night | | The Script | No Sound Without Silence | | Tom Jones | Long Lost Suitcase,Praise and Blame,Along Came Jones | +------------------------+----------------------------------------------------------------------------+
Hãy cẩn thận về độ dài!
Một điều quan trọng bạn cần biết khi sử dụng GROUP_CONCAT()
là kết quả bị cắt ngắn đến độ dài tối đa được cung cấp bởi group_concat_max_len
biến hệ thống, có giá trị mặc định là 1024
.
Giá trị của biến này có thể được đặt cao hơn, bằng cách sử dụng cú pháp sau:
SET [GLOBAL | SESSION] group_concat_max_len = val;
Ở đâu val
là một số nguyên không dấu.
Tuy nhiên, lưu ý rằng độ dài tối đa hiệu dụng của giá trị trả về tự nó bị giới hạn bởi giá trị của max_allowed_packet
.