GROUP_CONCAT, MySQL'de bir CONCAT içinde nasıl kullanılır


117

MySQL'de aşağıdaki verileri içeren bir tablom varsa:

id       Name       Value
1          A          4
1          A          5
1          B          8
2          C          9

bunu aşağıdaki formata nasıl getiririm?

id         Column
1          A:4,5,B:8
2          C:9


Sanırım kullanmalıyım GROUP_CONCAT. Ama nasıl çalıştığından emin değilim.

Yanıtlar:


160
select id, group_concat(`Name` separator ',') as `ColumnName`
from
(
  select 
    id, 
    concat(`Name`, ':', group_concat(`Value` separator ',')) as `Name`
  from mytbl
  group by 
    id, 
    `Name`
) tbl
group by id;

Burada uygulandığını görebilirsiniz: Sql Fiddle Demo . Tam olarak ihtiyacınız olan şey.

Bölmeyi iki adımda güncelleyin . Önce, benzersiz bir [Ad, kimlik] 'e karşı tüm değerleri (virgülle ayrılmış) içeren bir tablo elde ederiz. Sonra elde edilen tablodan tüm isimleri ve değerleri her benzersiz kimliğe karşı tek bir değer olarak alırız. Burada açıklanan buna bakın SQL Fiddle Demo (iki sonuç kümesine sahip olduğundan aşağı kaydırın)

Düzenle Soruyu okurken bir hata oldu, sadece id'ye göre gruplandırmıştım. Ancak iki group_contact gerekli ise (Değerler, Ad ve id'ye göre gruplanacak ve sonra tümü id'ye göre gruplanacak). Önceki cevap

select 
id,group_concat(concat(`name`,':',`value`) separator ',')
as Result from mytbl group by id

Burada uygulandığını görebilirsiniz: SQL Fiddle Demo


Bu Biswa'nın istediğini vermiyor.
eisberg

3
İnsanları yalnızca bir tür ayırıcı kullanmanın dezavantajlı olabileceği konusunda uyarmanın önemli olduğunu düşünüyorum. "Ad" ayırıcısını noktalı virgül (;) olarak yapmayı öneririm ve değerler ayırıcısı virgül (,) olarak kalabilir
Fandi Susanto

4
Ayrıca GROUP_CONCAT, çıktısını sessizce kısaltabileceğini lütfen unutmayın group_concat_max_len. SET group_concat_max_len=...yardımcı olacaktır, ancak yine de döndürülen (bayt?) uzunluğunun group_concat_max_len.
tuomassalo

2
Ayrıca group_concat'in tek bir NULL değeriyle karşılaştığını ve onu içeren tüm satırı atlayacağını unutmayın. Buradaki ikinci uyarıda bunun üzerinde çalışıyorum .
MatrixManAtYrService

1
Yanıt olarak verilen SQL Fiddle bağlantısıyla ilgili sorun yaşayan varsa. Çalışma Fiddle buradadır: sqlfiddle.com/#!9/42f994/601/0
Hitesh

21

Deneyin:

CREATE TABLE test (
  ID INTEGER,
  NAME VARCHAR (50),
  VALUE INTEGER
);

INSERT INTO test VALUES (1, 'A', 4);
INSERT INTO test VALUES (1, 'A', 5);
INSERT INTO test VALUES (1, 'B', 8);
INSERT INTO test VALUES (2, 'C', 9);

SELECT ID, GROUP_CONCAT(NAME ORDER BY NAME ASC SEPARATOR ',')
FROM (
  SELECT ID, CONCAT(NAME, ':', GROUP_CONCAT(VALUE ORDER BY VALUE ASC SEPARATOR ',')) AS NAME
  FROM test
  GROUP BY ID, NAME
) AS A
GROUP BY ID;

SQL Fiddle: http://sqlfiddle.com/#!2/b5abe/9/0


2
Evet eisberg +1. Cevabınız oldukça doğru ve daha erken. İlk cevabımda bir hata yaptım
Sami

9
SELECT ID, GROUP_CONCAT(CONCAT_WS(':', NAME, VALUE) SEPARATOR ',') AS Result 
FROM test GROUP BY ID

7
Cevabınıza bir açıklama ekleyebilirseniz iyi olur. Bu, bunu ve gelecekteki cevapları geliştirmek için bir öneridir. Teşekkürler!
Luís Cruz

5

Her şeyden önce, benzersiz olmayan bir kimliğe sahip olmanın nedenini görmüyorum, ancak sanırım başka bir tabloya bağlanan bir kimlik. İkinci olarak, sunucuyu yenen alt sorgulara gerek yoktur. Bunu tek bir sorguda yaparsınız, bunun gibi

SELECT id,GROUP_CONCAT(name, ':', value SEPARATOR "|") FROM sample GROUP BY id

Hızlı ve doğru sonuçlar alırsınız ve sonucu bu AYIRICI "|" ile bölebilirsiniz. Ben her zaman bu ayırıcıyı kullanırım çünkü onu bir dizge içinde bulmak imkansız, bu yüzden benzersizdir. İki A'ya sahip olmak sorun değil, sadece değeri belirlersiniz. Veya harfle birlikte bir sütun daha alabilirsin ki bu daha da iyi. Bunun gibi :

SELECT id,GROUP_CONCAT(DISTINCT(name)), GROUP_CONCAT(value SEPARATOR "|") FROM sample GROUP BY name

2
 SELECT id, GROUP_CONCAT(CONCAT_WS(':', Name, CAST(Value AS CHAR(7))) SEPARATOR ',') AS result 
    FROM test GROUP BY id

döküm veya dönüştürme kullanmalısınız, aksi takdirde BLOB iade edilecektir

sonuç

id         Column
1          A:4,A:5,B:8
2          C:9

sonucu python veya java gibi bir programla bir kez daha işlemelisiniz


0

IF OBJECT_ID('master..test') is not null Drop table test

CREATE TABLE test (ID INTEGER, NAME VARCHAR (50), VALUE INTEGER );
INSERT INTO test VALUES (1, 'A', 4);
INSERT INTO test VALUES (1, 'A', 5);
INSERT INTO test VALUES (1, 'B', 8);
INSERT INTO test VALUES (2, 'C', 9);

select distinct NAME , LIST = Replace(Replace(Stuff((select ',', +Value from test where name = _a.name for xml path('')), 1,1,''),'<Value>', ''),'</Value>','') from test _a order by 1 desc

Benim tablo adım test ve bitiştirme için XML Yolu ('') sözdizimini kullanıyorum. Stuff işlevi başka bir dizgeye bir dizge ekler. Başlangıç ​​konumundaki ilk dizedeki belirtilen uzunluktaki karakterleri siler ve ardından ikinci dizeyi başlangıç ​​konumundaki ilk dizeye ekler.

STUFF işlevleri şuna benzer: STUFF (karakter_ifadesi, başlangıç, uzunluk, karakter_ifadesi)

karakter_ifadesi, karakter verilerinin bir ifadesidir. karakter_ifadesi sabit, değişken veya karakter veya ikili verilerin bir sütunu olabilir.

başlangıç ​​Silme ve ekleme işleminin başlatılacağı konumu belirten bir tamsayı değeridir. Başlangıç ​​veya uzunluk negatifse, boş bir dize döndürülür. Başlangıç, ilk karakter_ifadesinden uzunsa, boş bir dize döndürülür. başlangıç ​​türü bigint olabilir.

uzunluk Silinecek karakter sayısını belirten bir tamsayıdır. Uzunluk ilk karakter_ifadesinden daha uzunsa, son karakter_ifadesinde son karaktere kadar silme gerçekleşir. uzunluk bigint türünde olabilir.


0

İd, Group_concat ( column) SEÇİN (SELECT id, Concat ( name, ':', Group_concat ( value)) OLARAK column mytbl GROUP BY id, name) tbl GROUP BY id;

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.