Resultados do MySQL como lista separada por vírgula

129

Eu preciso executar uma consulta como:

SELECT p.id, p.name, 
       (SELECT name 
          FROM sites s 
         WHERE s.id = p.site_id) AS site_list
  FROM publications p

Mas eu gostaria que a sub-seleção retornasse uma lista separada por vírgula, em vez de uma coluna de dados. Isso é possível e, em caso afirmativo, como?

Glen Solsberry
fonte

Respostas:

250

Você pode usar GROUP_CONCAT para fazer isso, por exemplo, algo como

SELECT p.id, p.name, GROUP_CONCAT(s.name) AS site_list
FROM sites s
INNER JOIN publications p ON(s.id = p.site_id)
GROUP BY p.id, p.name;
Paul Dixon
fonte
10
Além disso, observe rapidamente que, se você estiver usando o PHPMyAdmin e quiser gerar uma lista delimitada por vírgulas para a página, use-o GROUP_CONCAT(CAST(s.name AS CHAR)); caso contrário, ele retornará algo totalmente inútil [BLOB - 20 Bytes].
precisa saber é o seguinte
3
A intenção é boa e o MySQL permitirá isso, mas tenha cuidado (geralmente) com o uso do GROUP BY. Os itens na lista de seleção precisam ser agregados válidos no contexto da cláusula GROUP BY. Nesse caso, p.name não é estritamente válido. Qualquer banco de dados em conformidade com o padrão SQL tratará isso como um erro. Nesse caso, use MAX (p.name) na lista de seleção ou adicione p.name à cláusula GROUP BY. Como Paul provavelmente significa p.id para representar uma chave primária ou única, adicionar p.name à cláusula GROUP BY não terá impacto no resultado final.
Jon Armstrong - Xgc
Observe que você pode ter que definir o tamanho máximo para a sessão por stackoverflow.com/questions/2567000/…
sobelito 20/15
Muito obrigado! Você me ajudou muito!
André Agostinho
11

Em vez de usar, group concat()você pode usar apenasconcat()

Select concat(Col1, ',', Col2) as Foo_Bar from Table1;

editar isso funciona apenas no mySQL; O Oracle concat aceita apenas dois argumentos. No oracle, você pode usar algo como select col1 || ',' || col2 || ',' || col3 como foobar da tabela1; no servidor sql, você usaria + em vez de pipes.

Robert Quinn
fonte
2
Isso não deve trabalhar no caso GROUP BY, enquanto GROUP_CONCAT () irá concatenar conteúdo de uma única coluna
Aram Paronikyan
5

Agora só me deparei com essa situação e encontrei alguns recursos mais interessantes por aí GROUP_CONCAT. Espero que esses detalhes façam você se sentir interessante.

GROUP_CONCAT simples

SELECT GROUP_CONCAT(TaskName) 
FROM Tasks;

Resultado:

+------------------------------------------------------------------+
| GROUP_CONCAT(TaskName)                                           |
+------------------------------------------------------------------+
| Do garden,Feed cats,Paint roof,Take dog for walk,Relax,Feed cats |
+------------------------------------------------------------------+

GROUP_CONCAT com DISTINCT

SELECT GROUP_CONCAT(TaskName) 
FROM Tasks;

Resultado:

+------------------------------------------------------------------+
| GROUP_CONCAT(TaskName)                                           |
+------------------------------------------------------------------+
| Do garden,Feed cats,Paint roof,Take dog for walk,Relax,Feed cats |
+------------------------------------------------------------------+

GROUP_CONCAT com DISTINCT e ORDER BY

SELECT GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) 
FROM Tasks;

Resultado:

+--------------------------------------------------------+
| GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) |
+--------------------------------------------------------+
| Take dog for walk,Relax,Paint roof,Feed cats,Do garden |
+--------------------------------------------------------+

GROUP_CONCAT com DISTINCT e SEPARATOR

SELECT GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') 
FROM Tasks;

Resultado:

+----------------------------------------------------------------+
| GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ')                |
+----------------------------------------------------------------+
| Do garden + Feed cats + Paint roof + Relax + Take dog for walk |
+----------------------------------------------------------------+

GROUP_CONCAT e combinando colunas

SELECT GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') 
FROM Tasks;

Resultado:

+------------------------------------------------------------------------------------+
| GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ')                                 |
+------------------------------------------------------------------------------------+
| 1) Do garden 2) Feed cats 3) Paint roof 4) Take dog for walk 5) Relax 6) Feed cats |
+------------------------------------------------------------------------------------+

GROUP_CONCAT e resultados agrupados Suponha que os seguintes sejam os resultados antes de usarGROUP_CONCAT

+------------------------+--------------------------+
| ArtistName             | AlbumName                |
+------------------------+--------------------------+
| Iron Maiden            | Powerslave               |
| AC/DC                  | Powerage                 |
| Jim Reeves             | Singing Down the Lane    |
| Devin Townsend         | Ziltoid the Omniscient   |
| Devin Townsend         | Casualties of Cool       |
| Devin Townsend         | Epicloud                 |
| Iron Maiden            | Somewhere in Time        |
| Iron Maiden            | Piece of Mind            |
| Iron Maiden            | Killers                  |
| Iron Maiden            | No Prayer for the Dying  |
| The Script             | No Sound Without Silence |
| Buddy Rich             | Big Swing Face           |
| Michael Learns to Rock | Blue Night               |
| Michael Learns to Rock | Eternity                 |
| Michael Learns to Rock | Scandinavia              |
| Tom Jones              | Long Lost Suitcase       |
| Tom Jones              | Praise and Blame         |
| Tom Jones              | Along Came Jones         |
| Allan Holdsworth       | All Night Wrong          |
| Allan Holdsworth       | The Sixteen Men of Tain  |
+------------------------+--------------------------+
USE Music;
SELECT ar.ArtistName,
    GROUP_CONCAT(al.AlbumName)
FROM Artists ar
INNER JOIN Albums al
ON ar.ArtistId = al.ArtistId
GROUP BY ArtistName;

Resultado:

+------------------------+----------------------------------------------------------------------------+
| ArtistName             | GROUP_CONCAT(al.AlbumName)                                                 |
+------------------------+----------------------------------------------------------------------------+
| AC/DC                  | Powerage                                                                   |
| Allan Holdsworth       | All Night Wrong,The Sixteen Men of Tain                                    |
| Buddy Rich             | Big Swing Face                                                             |
| Devin Townsend         | Epicloud,Ziltoid the Omniscient,Casualties of Cool                         |
| Iron Maiden            | Somewhere in Time,Piece of Mind,Powerslave,Killers,No Prayer for the Dying |
| Jim Reeves             | Singing Down the Lane                                                      |
| Michael Learns to Rock | Eternity,Scandinavia,Blue Night                                            |
| The Script             | No Sound Without Silence                                                   |
| Tom Jones              | Long Lost Suitcase,Praise and Blame,Along Came Jones                       |
+------------------------+----------------------------------------------------------------------------+
Ganesa Vijayakumar
fonte
3

No meu caso, tenho que concatenar todo o número da conta de uma pessoa cujo número de celular é único. Então, eu usei a seguinte consulta para conseguir isso.

SELECT GROUP_CONCAT(AccountsNo) as Accounts FROM `tblaccounts` GROUP BY MobileNumber

O resultado da consulta está abaixo:

Accounts
93348001,97530801,93348001,97530801
89663501
62630701
6227895144840002
60070021
60070020
60070019
60070018
60070017
60070016
60070015
Vignesh Chinnaiyan
fonte