Bisakah saya menggabungkan beberapa baris MySQL menjadi satu bidang?

1214

Dengan menggunakan MySQL, saya dapat melakukan sesuatu seperti:

SELECT hobbies FROM peoples_hobbies WHERE person_id = 5;

Output saya:

shopping
fishing
coding

tetapi saya hanya ingin 1 baris, 1 col:

Output yang Diharapkan:

shopping, fishing, coding

Alasannya adalah bahwa saya memilih beberapa nilai dari beberapa tabel, dan setelah semua bergabung, saya punya lebih banyak baris daripada yang saya inginkan.

Saya telah mencari fungsi di MySQL Doc dan tidak terlihat seperti CONCATatau CONCAT_WSfungsi menerima set hasil.

Jadi, apakah ada orang di sini yang tahu bagaimana melakukan ini?

Dean Sebaliknya
sumber
9
Saya baru saja menulis demo kecil tentang cara menggunakan group_concat yang mungkin berguna bagi Anda: giombetti.com/2013/06/06/mysql-group_concat
Marc Giombetti

Jawaban:

1739

Anda bisa menggunakan GROUP_CONCAT:

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

Seperti yang dikatakan Ludwig dalam komentarnya, Anda dapat menambahkan DISTINCToperator untuk menghindari duplikat:

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

Seperti yang dinyatakan Jan dalam komentar mereka, Anda juga bisa mengurutkan nilai sebelum mengimplementasikannya menggunakan ORDER BY:

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

Seperti yang dinyatakan Dag dalam komentarnya, ada batas 1024 byte pada hasilnya. Untuk mengatasi ini, jalankan kueri ini sebelum kueri Anda:

SET group_concat_max_len = 2048;

Tentu saja, Anda dapat mengubah 2048sesuai dengan kebutuhan Anda. Untuk menghitung dan menetapkan nilainya:

SET group_concat_max_len = CAST(
    (SELECT SUM(LENGTH(hobbies)) + COUNT(*) * LENGTH(', ')
    FROM peoples_hobbies 
    GROUP BY person_id)
    AS UNSIGNED
);
che
sumber
155
Perlu diketahui batasan 1024 byte di kolom yang dihasilkan (lihat parameter group_concat_max_len )
Dag
81
Dan menambahkan DISTINCTparameter, Anda tidak akan mendapatkan ganda. ... GROUP_CONCAT(DISTINCT hobbies)
Ludwig
3
Kebutuhan saya adalah untuk mendapatkan SEMUA data dari satu kolom. Jangan gunakan klausa GROUP BY untuk melakukan ini. Contoh: SELECT GROUP_CONCAT (email SEPARATOR ',') DARI pengguna;
Jonathan Bergeron
1
Terima kasih, saya tidak tahu ada batasan panjang grup. Saya perlu itu untuk berkeliling daftar monster yang saya hasilkan.
Patrick
9
Jika Anda ingin hobi semacam digunakan tali meledak yang dihasilkan:SELECT person_id, GROUP_CONCAT(hobbies ORDER BY hobbies ASC SEPARATOR ', ') FROM peoples_hobbies GROUP BY person_id
Jan
106

Lihat GROUP_CONCATapakah versi MySQL Anda (4.1) mendukungnya. Lihat dokumentasi untuk lebih jelasnya.

Itu akan terlihat seperti:

  SELECT GROUP_CONCAT(hobbies SEPARATOR ', ') 
  FROM peoples_hobbies 
  WHERE person_id = 5 
  GROUP BY 'all';
lpfavreau
sumber
11
Saya pikir itu group by 'all'tidak perlu (apalagi yang tidak diinginkan), karena ini menetapkan untuk semua baris string alldan kemudian membandingkan string antara baris ini. Apakah saya benar?
Krzysiek
74

Sintaks alternatif untuk menggabungkan beberapa baris individual

PERINGATAN: Posting ini akan membuat Anda lapar.

Diberikan:

Saya mendapati diri saya ingin memilih beberapa baris individual — bukan grup — dan bergabung dalam bidang tertentu.

Katakanlah Anda memiliki tabel id produk dan nama serta harganya:

+------------+--------------------+-------+
| 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 |
+------------+--------------------+-------+

Maka Anda memiliki beberapa ajax schmancy mewah yang mencantumkan anak-anak anjing ini sebagai kotak centang.

Pengguna hippo lapar Anda memilih 13, 15, 16. Tidak ada makanan penutup untuknya hari ini ...

Temukan:

Cara untuk meringkas pesanan pengguna Anda dalam satu baris, dengan mysql murni.

Larutan:

Gunakan GROUP_CONCATdengan para INklausa :

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

Output yang mana:

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

Solusi Bonus:

Jika Anda juga ingin harga total, masukkan 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 |
+------------------------------------------------+-------+

PS: Permintaan maaf jika Anda tidak memiliki In-N-Out di dekatnya ...

elbowlobstercowstand
sumber
11
Meskipun ini adalah jawaban yang bagus, ini kedengarannya lebih seperti iklan daripada hanya menjawab. Masih jawaban yang terformat dengan baik.
FliiFe
1
Bisakah saya mendapatkan bantuan stackoverflow.com/q/60278898/11697039 @elbowlobstercowstand
zus
39

Anda dapat mengubah panjang maks GROUP_CONCATnilai dengan mengatur group_concat_max_lenparameter.

Lihat detail dalam dokumentasi MySQL .

pau.moreno
sumber
25

Dalam kasus saya, saya memiliki deretan Id, dan itu perlu untuk melemparkannya ke char, jika tidak, hasilnya dikodekan ke dalam format biner:

SELECT CAST(GROUP_CONCAT(field SEPARATOR ',') AS CHAR) FROM table
Fedir RYKHTIK
sumber
1
Terima kasih! Tanpa CASTsaya punya nilai SEPERTI [BLOB - 14 Bytes]dalam hasil!
Mel_T
1
Bisakah saya mendapatkan bantuan stackoverflow.com/q/60278898/11697039 @Fedir RYKHTIK
zus
16

Gunakan variabel sesi MySQL (5.6.13) dan operator penugasan seperti berikut

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

maka kamu bisa mendapatkan

test1,test11
Shen liang
sumber
2
apakah ini lebih cepat dari GROUP_CONCAT?
jave.web
1
Saya menguji ini di bawah PHPMyAdmin dengan server MySQL v5.6.17 pada kolom deskripsi (varchar (50)) di tabel uji tetapi mengembalikan bidang Gumpalan untuk setiap catatan:SELECT @logmsg := CONCAT_ws(',',@logmsg,description) from test
Jan
14

Saya memiliki kueri yang lebih rumit, dan menemukan bahwa saya harus menggunakan GROUP_CONCATkueri luar untuk membuatnya berfungsi:

Permintaan Asli:

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

Meledak:

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

Semoga ini bisa membantu seseorang.

Alex Bowyer
sumber
9

Untuk seseorang yang mencari di sini cara menggunakan GROUP_CONCATdengan subquery - memposting contoh ini

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

Jadi GROUP_CONCATharus digunakan di dalam subquery, bukan membungkusnya.

Oleg Abrazhaev
sumber
1
Ini persis apa yang saya cari
bumerang
7

Coba ini:

DECLARE @Hobbies NVARCHAR(200) = ' '

SELECT @Hobbies = @Hobbies + hobbies + ',' FROM peoples_hobbies WHERE person_id = 5;
thejustv
sumber
2
Inilah yang saya dapatkan: 'Jenis pernyataan tidak dikenal. (dekat "DECLARE" di posisi 0) '
Istiaque Ahmed
1

kami memiliki dua cara untuk menggabungkan kolom di MySql

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

Atau

select group_concat(hobbies) as `Hobbies` from people_hobbies where 1
raghavendra
sumber