Comment utiliser GROUP_CONCAT dans un CONCAT dans MySQL

117

Si j'ai une table avec les données suivantes dans MySQL:

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

comment puis-je obtenir le format suivant?

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


Je pense que je dois utiliser GROUP_CONCAT. Mais je ne sais pas comment cela fonctionne.

Biswa
la source

Réponses:

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;

Vous pouvez le voir implémenté ici: Sql Fiddle Demo . Exactement ce dont vous avez besoin.

Mettez à jour le fractionnement en deux étapes. Tout d'abord, nous obtenons une table contenant toutes les valeurs (séparées par des virgules) par rapport à un [Name, id] unique. Ensuite, à partir de la table obtenue, nous obtenons tous les noms et valeurs sous forme de valeur unique par rapport à chaque identifiant unique Voir ceci expliqué ici Démo SQL Fiddle (défilement vers le bas comme il a deux ensembles de résultats)

Edit Il y a eu une erreur dans la lecture de la question, je n'avais groupé que par id. Mais deux group_contacts sont nécessaires si (les valeurs doivent être concaténées groupées par nom et id, puis par id). La réponse précédente était

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

Vous pouvez le voir implémenté ici: Démo SQL Fiddle

Sami
la source
Cela ne donne pas ce que Biswa a demandé.
eisberg
3
Je pense qu'il est important d'avertir les peuples que l'utilisation d'un seul type de séparateur pourrait être désavantageuse. Je suggère de faire le séparateur "nom" comme point-virgule (;), et le séparateur de valeurs peut rester comme virgule (,)
Fandi Susanto
4
Veuillez également noter que cela GROUP_CONCATpourrait tronquer silencieusement sa sortie vers group_concat_max_len. SET group_concat_max_len=...aidera, mais c'est quand même une bonne idée de vérifier que la longueur (octet?) renvoyée est inférieure à group_concat_max_len.
tuomassalo
2
Notez également que group_concat rencontre une seule valeur NULL, il omettra la ligne entière qui la contenait. Je travaille autour de cela dans la deuxième mise en garde ici .
MatrixManAtYrService
1
Si quelqu'un est confronté à un problème avec le lien SQL Fiddle donné en réponse. Working Fiddle est ici: sqlfiddle.com/#!9/42f994/601/0
Hitesh
21

Essayer:

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

Eisberg
la source
2
Oui eisberg +1. Votre réponse est assez précise et antérieure. J'ai fait une erreur dans ma première réponse
Sami
9
SELECT ID, GROUP_CONCAT(CONCAT_WS(':', NAME, VALUE) SEPARATOR ',') AS Result 
FROM test GROUP BY ID
John
la source
7
Ce serait bien si vous pouviez ajouter une description à votre réponse. Ceci est une suggestion pour améliorer ceci et les réponses futures. Merci!
Luís Cruz
5

Tout d'abord, je ne vois pas la raison d'avoir un ID qui n'est pas unique, mais je suppose que c'est un ID qui se connecte à une autre table. Deuxièmement, il n'y a pas besoin de sous-requêtes, ce qui bat le serveur. Vous faites cela en une seule requête, comme ceci

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

Vous obtenez des résultats rapides et corrects, et vous pouvez diviser le résultat par ce SEPARATEUR "|". J'utilise toujours ce séparateur, car il est impossible de le trouver dans une chaîne, c'est pourquoi il est unique. Il n'y a aucun problème à avoir deux A, vous n'identifiez que la valeur. Ou vous pouvez avoir une colonne de plus, avec la lettre, ce qui est encore mieux. Comme ça :

SELECT id,GROUP_CONCAT(DISTINCT(name)), GROUP_CONCAT(value SEPARATOR "|") FROM sample GROUP BY name
Lucian Minea
la source
2
 SELECT id, GROUP_CONCAT(CONCAT_WS(':', Name, CAST(Value AS CHAR(7))) SEPARATOR ',') AS result 
    FROM test GROUP BY id

vous devez utiliser cast ou convertir, sinon vous retournerez BLOB

le résultat est

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

vous devez à nouveau gérer le résultat par un programme tel que python ou java

lglcomcn
la source
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

Mon nom de table est test, et pour la concatination, j'utilise la syntaxe For XML Path (''). La fonction stuff insère une chaîne dans une autre chaîne. Il supprime une longueur spécifiée de caractères dans la première chaîne à la position de départ, puis insère la deuxième chaîne dans la première chaîne à la position de départ.

Les fonctions STUFF ressemblent à ceci: STUFF (expression_caractère, début, longueur, expression_caractère)

expression_caractère Est une expression de données de caractère. expression_caractère peut être une constante, une variable ou une colonne de données caractères ou binaires.

start Est une valeur entière qui spécifie l'emplacement de démarrage de la suppression et de l'insertion. Si le début ou la longueur est négatif, une chaîne nulle est renvoyée. Si start est plus long que la première expression_caractère, une chaîne nulle est renvoyée. start peut être de type bigint.

length Est un entier qui spécifie le nombre de caractères à supprimer. Si la longueur est plus longue que la première expression_caractère, la suppression se produit jusqu'au dernier caractère de la dernière expression_caractère. la longueur peut être de type bigint.

Novy
la source
0

SELECT id, Group_concat ( column) FROM (SELECT id, Concat ( name, ':', Group_concat ( value)) AS column FROM mytbl GROUP BY id, nom) tbl GROUP BY id;

Mrigank Shekhar
la source