Come utilizzare GROUP_CONCAT in un CONCAT in MySQL


117

Se ho una tabella con i seguenti dati in MySQL:

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

come lo ottengo nel seguente formato?

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


Penso di dover usare GROUP_CONCAT. Ma non sono sicuro di come funzioni.

Risposte:


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;

Puoi vederlo implementato qui: Sql Fiddle Demo . Esattamente quello che ti serve.

Aggiorna la divisione in due passaggi. Per prima cosa otteniamo una tabella con tutti i valori (separati da virgole) contro un [Nome, ID] univoco. Quindi dalla tabella ottenuta otteniamo tutti i nomi e i valori come un singolo valore contro ogni ID univoco Vedi questo spiegato qui Demo di SQL Fiddle (scorri verso il basso poiché ha due set di risultati)

Modifica C'è stato un errore nella lettura della domanda, l'avevo raggruppata solo per id. Ma sono necessari due group_contacts se (i valori devono essere concatenati raggruppati per nome e id e quindi su tutti per id). La risposta precedente era

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

Puoi vederlo implementato qui: SQL Fiddle Demo


Questo non dà ciò che Biswa ha chiesto.
eisberg

3
Penso che sia importante avvertire le persone che l'utilizzo di un solo tipo di separatore potrebbe essere svantaggioso. Suggerisco di impostare il separatore "nome" come punto e virgola (;), e il separatore dei valori può rimanere come virgola (,)
Fandi Susanto

4
Si noti inoltre che GROUP_CONCATpotrebbe troncare silenziosamente il suo output a group_concat_max_len. SET group_concat_max_len=...aiuterà, ma è comunque una buona idea controllare che la lunghezza restituita (byte?) sia minore di group_concat_max_len.
tuomassalo

2
Nota anche che group_concat incontra un singolo valore NULL e ometterà l'intera riga che lo conteneva. Lavoro intorno a questo nel secondo avvertimento qui .
MatrixManAtYrService

1
Se qualcuno ha problemi con il collegamento SQL Fiddle fornito in risposta. Working Fiddle è qui: sqlfiddle.com/#!9/42f994/601/0
Hitesh

21

Provare:

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
Sì eisberg +1. La tua risposta è più o meno accurata e precedente. Ho commesso un errore nella mia prima risposta
Sami

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

7
Sarebbe bello se potessi aggiungere qualche descrizione alla tua risposta. Questo è un suggerimento per migliorare questa e le risposte future. Grazie!
Luís Cruz

5

Prima di tutto, non vedo il motivo per avere un ID non univoco, ma immagino che sia un ID che si collega a un'altra tabella. Secondo, non c'è bisogno di sottoquery, il che picchia il server. Lo fai in una query, come questa

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

Ottieni risultati rapidi e corretti e puoi dividere il risultato per quel SEPARATORE "|". Uso sempre questo separatore, perché è impossibile trovarlo all'interno di una stringa, quindi è unico. Non c'è problema ad avere due A, identifichi solo il valore. Oppure puoi avere un'altra colonna, con la lettera, che è ancora meglio. Come questo :

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

devi usare cast o convert, altrimenti verrà restituito BLOB

il risultato è

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

devi gestire il risultato ancora una volta da programmi come python o java


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

Il nome della mia tabella è test e per la concatinazione utilizzo la sintassi For XML Path (''). La funzione stuff inserisce una stringa in un'altra stringa. Elimina una lunghezza di caratteri specificata nella prima stringa nella posizione iniziale e quindi inserisce la seconda stringa nella prima stringa nella posizione iniziale.

Le funzioni STUFF hanno questo aspetto: STUFF (character_expression, start, length, character_expression)

character_expression È un'espressione di dati carattere. character_expression può essere una costante, una variabile o una colonna di dati carattere o binari.

inizio È un valore intero che specifica la posizione in cui iniziare l'eliminazione e l'inserimento. Se start o length è negativo, viene restituita una stringa nulla. Se start è più lungo della prima character_expression, viene restituita una stringa nulla. inizio può essere di tipo bigint.

length È un numero intero che specifica il numero di caratteri da eliminare. Se la lunghezza è maggiore della prima espressione_carattere, la cancellazione avviene fino all'ultimo carattere nell'ultima espressione_carattere. la lunghezza può essere di tipo bigint.


0

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.