Tôi có thể ghép nhiều hàng MySQL vào một trường không?


1214

Sử dụng MySQL, tôi có thể làm một cái gì đó như:

SELECT hobbies FROM peoples_hobbies WHERE person_id = 5;

Đầu ra của tôi:

shopping
fishing
coding

nhưng thay vào đó tôi chỉ muốn 1 hàng, 1 col:

Đầu ra dự kiến:

shopping, fishing, coding

Lý do là tôi đang chọn nhiều giá trị từ nhiều bảng và sau tất cả các phép nối tôi đã có nhiều hàng hơn tôi muốn.

Tôi đã tìm kiếm một chức năng trên MySQL Doc và nó không giống nhưCONCAT hoặc CONCAT_WSchức năng chấp nhận tập kết quả.

Vì vậy, có ai ở đây biết làm thế nào để làm điều này?


9
Tôi vừa viết một bản demo nhỏ về cách sử dụng group_concat có thể hữu ích với bạn: giombetti.com/2013/06/06/mysql-group_concat
Marc Giombetti

Câu trả lời:


1739

Bạn có thể sử dụng GROUP_CONCAT:

SELECT person_id, GROUP_CONCAT(hobbies SEPARATOR ', ')
FROM peoples_hobbies
GROUP BY person_id;

Như Ludwig đã nêu trong nhận xét của mình, bạn có thể thêm DISTINCTtoán tử để tránh trùng lặp:

SELECT person_id, GROUP_CONCAT(DISTINCT hobbies SEPARATOR ', ')
FROM peoples_hobbies 
GROUP BY person_id;

Như Jan đã nêu trong nhận xét của họ, bạn cũng có thể sắp xếp các giá trị trước khi mã hóa nó bằng cách sử dụng ORDER BY:

SELECT person_id, GROUP_CONCAT(hobbies ORDER BY hobbies ASC SEPARATOR ', ')
FROM peoples_hobbies
GROUP BY person_id;

Như Dag đã nêu trong nhận xét của mình, kết quả có giới hạn 1024 byte. Để giải quyết vấn đề này, hãy chạy truy vấn này trước truy vấn của bạn:

SET group_concat_max_len = 2048;

Tất nhiên, bạn có thể thay đổi 2048theo nhu cầu của bạn. Để tính toán và gán giá trị:

SET group_concat_max_len = CAST(
    (SELECT SUM(LENGTH(hobbies)) + COUNT(*) * LENGTH(', ')
    FROM peoples_hobbies 
    GROUP BY person_id)
    AS UNSIGNED
);

155
Chỉ cần lưu ý về giới hạn 1024 byte trong cột kết quả (xem tham số group_concat_max_len )
Dag

81
Và thêm DISTINCTtham số, bạn sẽ không nhận được bất kỳ gấp đôi. ... GROUP_CONCAT(DISTINCT hobbies)
Ludwig

3
Nhu cầu của tôi là lấy TẤT CẢ dữ liệu từ một cột. Đừng sử dụng mệnh đề GROUP BY để làm điều này. Ví dụ: CHỌN GROUP_CONCAT (email SEPARATOR ',') TỪ người dùng;
Jonathan Bergeron

1
Cảm ơn, tôi không biết có giới hạn độ dài concat nhóm. Tôi cần điều đó để có được một danh sách quái vật tôi tạo ra.
Patrick

9
Nếu bạn muốn sắp xếp sở thích trong chuỗi kết quả được mã hóa, hãy sử dụng:SELECT person_id, GROUP_CONCAT(hobbies ORDER BY hobbies ASC SEPARATOR ', ') FROM peoples_hobbies GROUP BY person_id
Jan

106

Hãy xem GROUP_CONCATnếu phiên bản MySQL của bạn (4.1) hỗ trợ nó. Xem tài liệu để biết thêm chi tiết.

Nó sẽ trông giống như:

  SELECT GROUP_CONCAT(hobbies SEPARATOR ', ') 
  FROM peoples_hobbies 
  WHERE person_id = 5 
  GROUP BY 'all';

11
Tôi nghĩ rằng điều đó group by 'all'là không cần thiết (hơn nữa là không mong muốn), bởi vì điều này gán cho tất cả các chuỗi hàng allvà sau đó so sánh các chuỗi giữa các hàng này. Tôi có đúng không
Krzysiek

74

Cú pháp thay thế để nối nhiều hàng, từng hàng

CẢNH BÁO: Bài đăng này sẽ làm bạn đói.

Được:

Tôi thấy mình muốn chọn nhiều hàng riêng lẻ của một nhóm Nhóm và nối vào một lĩnh vực nhất định.

Giả sử bạn có một bảng id sản phẩm, tên và giá của chúng:

+------------+--------------------+-------+
| product_id | name               | price |
+------------+--------------------+-------+
|         13 | Double Double      |     5 |
|         14 | Neapolitan Shake   |     2 |
|         15 | Animal Style Fries |     3 |
|         16 | Root Beer          |     2 |
|         17 | Lame T-Shirt       |    15 |
+------------+--------------------+-------+

Sau đó, bạn có một số ajax ưa ​​thích liệt kê những con chó con này như là hộp kiểm.

Người dùng hà mã đói của bạn chọn 13, 15, 16. Hôm nay không có món tráng miệng nào cho cô ấy ...

Tìm thấy:

Một cách để tóm tắt thứ tự người dùng của bạn trong một dòng, với mysql thuần túy.

Giải pháp:

Sử dụng GROUP_CONCATvới các INđiều khoản :

mysql> SELECT GROUP_CONCAT(name SEPARATOR ' + ') AS order_summary FROM product WHERE product_id IN (13, 15, 16);

Đầu ra nào:

+------------------------------------------------+
| order_summary                                  |
+------------------------------------------------+
| Double Double + Animal Style Fries + Root Beer |
+------------------------------------------------+

Giải pháp thưởng:

Nếu bạn muốn tổng giá quá, hãy ném vào SUM():

mysql> SELECT GROUP_CONCAT(name SEPARATOR ' + ') AS order_summary, SUM(price) AS total FROM product WHERE product_id IN (13, 15, 16);
+------------------------------------------------+-------+
| order_summary                                  | total |
+------------------------------------------------+-------+
| Double Double + Animal Style Fries + Root Beer |    10 |
+------------------------------------------------+-------+

Tái bút: Xin lỗi nếu bạn không có In-N-Out gần đó ...


11
Mặc dù đây là một câu trả lời tốt, nhưng điều này nghe giống như quảng cáo hơn là trả lời đơn thuần. Vẫn là một câu trả lời tốt.
FliiFe

1
Tôi có thể nhận trợ giúp stackoverflow.com/q/60278898/11697039 @elbowlobstercowstand
zus

39

Bạn có thể thay đổi độ dài tối đa của GROUP_CONCATgiá trị bằng cách đặt group_concat_max_lentham số.

Xem chi tiết trong tài liệu MySQL .



25

Trong trường hợp của tôi, tôi đã có một hàng Id và không cần thiết phải chuyển nó thành char, nếu không, kết quả được mã hóa thành định dạng nhị phân:

SELECT CAST(GROUP_CONCAT(field SEPARATOR ',') AS CHAR) FROM table

1
Cảm ơn! Không có CASTtôi có giá trị THÍCH [BLOB - 14 Bytes]trong kết quả!
Mel_T

1
Tôi có thể nhận trợ giúp stackoverflow.com/q/60278898/11697039 @Fedir RYKHTIK
zus

16

Sử dụng biến phiên và toán tử gán phiên của MySQL (5.6.13) như sau

SELECT @logmsg := CONCAT_ws(',',@logmsg,items) FROM temp_SplitFields a;

sau đó bạn có thể nhận được

test1,test11

2
nó có nhanh hơn GROUP_CONCAT không?
jave.web

1
Tôi đã thử nghiệm điều này trong PHPMyAdmin với máy chủ MySQL v5.6.17 trên cột mô tả (varchar (50)) trong bảng thử nghiệm nhưng nó trả về trường BLOB cho mỗi bản ghi:SELECT @logmsg := CONCAT_ws(',',@logmsg,description) from test
Jan

14

Tôi đã có một truy vấn phức tạp hơn và thấy rằng tôi phải sử dụng GROUP_CONCATtrong một truy vấn bên ngoài để làm cho nó hoạt động:

Truy vấn gốc:

SELECT DISTINCT userID 
FROM event GROUP BY userID 
HAVING count(distinct(cohort))=2);

Đã mã hóa:

SELECT GROUP_CONCAT(sub.userID SEPARATOR ', ') 
FROM (SELECT DISTINCT userID FROM event 
GROUP BY userID HAVING count(distinct(cohort))=2) as sub;

Hy vọng điều này có thể giúp một ai đó.


9

Đối với ai đó đang tìm kiếm cách sử dụng GROUP_CONCATvới truy vấn con - đăng ví dụ này

SELECT i.*,
(SELECT GROUP_CONCAT(userid) FROM favourites f WHERE f.itemid = i.id) AS idlist
FROM items i
WHERE i.id = $someid

Vì vậy, GROUP_CONCATphải được sử dụng bên trong truy vấn con, không gói nó.


1
Đây chính xác là những gì tôi đang tìm kiếm
bumerang

7

Thử cái này:

DECLARE @Hobbies NVARCHAR(200) = ' '

SELECT @Hobbies = @Hobbies + hobbies + ',' FROM peoples_hobbies WHERE person_id = 5;

2
Đây là những gì tôi nhận được: 'Loại câu lệnh không được công nhận. (gần "
KHAI THÁC

1

chúng ta có hai cách để nối các cột trong MySql

select concat(hobbies) as `Hobbies` from people_hobbies where 1

Hoặc là

select group_concat(hobbies) as `Hobbies` from people_hobbies where 1
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.