Birden fazla MySQL satırını bir alanda birleştirebilir miyim?


1214

Kullanarak MySQL, şöyle bir şey yapabilirim:

SELECT hobbies FROM peoples_hobbies WHERE person_id = 5;

Çıktım:

shopping
fishing
coding

ama onun yerine sadece 1 satır, 1 col istiyorum:

Beklenen çıktı:

shopping, fishing, coding

Bunun nedeni, birden çok tablodan birden fazla değer seçmem ve tüm birleştirmelerden sonra istediğimden çok daha fazla satır var.

Ben MySQL Doc bir işlevi aradım ve gibi görünmüyor CONCATya da CONCAT_WSişlevleri sonuç kümelerini kabul.

Peki burada kimse bunu nasıl yapacağını biliyor mu?


9
Size faydalı olabilecek group_concat'in nasıl kullanılacağı hakkında küçük bir demo yazdım: giombetti.com/2013/06/06/mysql-group_concat
Marc Giombetti

Yanıtlar:


1739

Şunları kullanabilirsiniz GROUP_CONCAT:

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

Ludwig'in yorumunda belirttiği gibi ,DISTINCT yinelemeleri önlemek için operatörü ekleyebilirsiniz :

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

Jan belirtildiği gibi kendi yorumunu, şunları yapabilirsiniz kullanarak imploding önce de sıralama değerleri ORDER BY:

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

Dag'ın yorumunda belirttiği gibi , sonuçta 1024 baytlık bir sınır var. Bu sorunu çözmek için sorgunuzdan önce bu sorguyu çalıştırın:

SET group_concat_max_len = 2048;

Tabii ki, 2048ihtiyaçlarınıza göre değiştirebilirsiniz . Değeri hesaplamak ve atamak için:

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

154
Sonuçta elde edilen sütundaki 1024 bayt sınırlamasının farkında olun (bkz. Group_concat_max_len parametresi )
Dag

81
Ve DISTINCTparametreyi eklediğinizde, iki katına çıkmayacaksınız. ... GROUP_CONCAT(DISTINCT hobbies)
Ludwig

3
Benim ihtiyacım bir sütundan TÜM verileri almak oldu. Bunu yapmak için GROUP BY deyimini kullanmayın. Örnek: SELECT GROUP_CONCAT (e-posta SEPARATOR ',') kullanıcılardan;
Jonathan Bergeron

1
Teşekkürler, grup concat uzunluk sınırı olduğunu bilmiyordum. Oluşturduğum bir canavar listesinde dolaşmak için buna ihtiyacım vardı.
Patrick

9
Sonuçta ortaya çıkan dize kullanımında hobileri sıralamak istiyorsanız:SELECT person_id, GROUP_CONCAT(hobbies ORDER BY hobbies ASC SEPARATOR ', ') FROM peoples_hobbies GROUP BY person_id
Jan

106

Göz at GROUP_CONCATMySQL sürümü (4.1) destekliyorsa. Daha fazla ayrıntı için belgelere bakın.

Şöyle bir şey olurdu:

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

11
Bunun group by 'all'gerekli olmadığını düşünüyorum (ayrıca istenmeyen), çünkü bu tüm satırlar dizesine atar allve sonra bu satırlar arasındaki dizeleri karşılaştırır. Haklı mıyım?
Krzysiek

74

Birden çok, tekli satırı birleştirmek için alternatif sözdizimi

UYARI: Bu yazı sizi acıktıracaktır.

Verilen:

Kendimi , bir grubun içinde olmayan , birden çok bireysel satır seçmek ve belirli bir alanda birleştirmek istedim .

Diyelim ki ürün kimlikleri, adları ve fiyatları içeren bir tablonuz var:

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

Sonra bu yavruları onay kutuları olarak listeleyen bazı fantezi-schmancy ajax var.

Aç su aygırı kullanıcınız seçer 13, 15, 16 . Bugün onun için tatlı yok ...

bul:

Saf mysql ile kullanıcı siparişinizi tek satırda özetlemenin bir yolu.

Çözüm:

Kullanım GROUP_CONCATile fıkra :IN

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

Hangi çıktılar:

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

Bonus Çözümü:

Toplam fiyatı da istiyorsanız, şunu girin 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 |
+------------------------------------------------+-------+

Not: Yakınlarda bir In-N-Out yoksa özür dileriz ...


11
Bu iyi bir cevap olmasına rağmen, bu sadece cevaplamaktan çok reklamcılık gibi geliyor. Hala iyi biçimlendirilmiş bir cevap.
FliiFe

1
Yardım alabilir miyim stackoverflow.com/q/60278898/11697039 @elbowlobstercowstand
zus

39

Ayarlanan GROUP_CONCATdeğeri ayarlayarak değerin maksimum uzunluğunu değiştirebilirsiniz .group_concat_max_lenParametreyi .

MySQL belgelerinde ayrıntıları inceleyin .



25

Benim durumumda Ids bir satır vardı ve char için döküm gerekli oldu, aksi takdirde sonuç ikili biçimde kodlanmış:

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

1
Teşekkürler! CASTBen [BLOB - 14 Bytes]sonuçta GİBİ değerler olmadan vardı !
Mel_T

1
Can i yardım almak stackoverflow.com/q/60278898/11697039 @Fedir RYKHTIK
zus

16

MySQL (5.6.13) oturum değişkenini ve atama operatörünü aşağıdaki gibi kullanın

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

o zaman alabilirsin

test1,test11

2
GROUP_CONCAT'tan daha mı hızlı?
jave.web

1
Ben bir test tablosundaki bir açıklama sütununda (varchar (50)) MySQL sunucusu v5.6.17 ile PHPMyAdmin altında test ama her kayıt için bir BLOB alanı döndürür:SELECT @logmsg := CONCAT_ws(',',@logmsg,description) from test
Jan

14

Daha karmaşık bir sorgu vardı GROUP_CONCATve işe almak için bir dış sorgu kullanmak zorunda bulundu :

Orijinal Sorgu:

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

imploded:

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

Umarım bu birine yardımcı olabilir.


9

Buraya bakan birisi için GROUP_CONCATalt sorgu ile nasıl kullanılacağı - bu örneği gönderme

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

Bu yüzden GROUP_CONCATalt sorgunun içinde kullanılmalı, sarılmamalıdır.


1
Bu tam olarak aradığım şeydi
bumerang

7

Bunu dene:

DECLARE @Hobbies NVARCHAR(200) = ' '

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

2
Ne var: 'Tanınmayan ifade türü. (0 konumunda "DECLARE" yakınında)
Istiaque Ahmed

1

MySql'de sütunları birleştirmenin iki yolu var

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

Veya

select group_concat(hobbies) as `Hobbies` from people_hobbies where 1
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.