MySQL GROUP_CONCAT: a formatação do output
-
06-07-2019 - |
Pergunta
Atualmente tenho a seguinte consulta:
SELECT group_concat(DISTINCT usrFirst, usrLast) as receiver_name //etc
Ao usar o PHP, ele gera minha lista de nomes da seguinte forma:
<?php
echo $row['receiver_name'];
//Outputs: JohnDoe,BillSmith,DaveJones
//Desired output: John Doe, Bill Smith, and Dave Jones
Eu preciso de ajuda para descobrir três coisas:
-
Como posso colocar um espaço entre o primeiro e último nome?
-
Como pode inserir um espaço após cada vírgula?
-
Como posso adicionar um 'e' direita antes do último nome exibido?
Solução
Eu não tenho certeza que você deve intimidar MySQL a fazer exatamente o que você quer lá. Eu sugiro usar o seguinte:
SELECT DISTINCT CONCAT(first, ' ', last) AS receiver_name
FROM names;
Em seguida, percorrer este conjunto de resultados em PHP e lidar com o caso de 'e' lá.
Se o desempenho é uma preocupação (você estará fazendo esta consulta frequentemente). Você se beneficiaria de não usar DISTINCT no valor calculado de CONCAT (primeira, '', passado) como que exigiria o uso de uma tabela temporária.
Para ajustá-lo, adicione o seguinte índice:
ALTER TABLE names ADD INDEX (last, first);
E alterar a sua consulta a seguinte:
SELECT CONCAT(first, ' ', last) AS receiver_name
FROM names
GROUP BY last, first;
Você será capaz de obter os seus valores diretamente a partir do índice, sem recorrer a uma tabela temporária ou filesort.
Tanto quanto o loop vai, algo como o seguinte iria funcionar:
<?php
$mysqli = new mysqli(/* connection info */);
$sql = "SELECT CONCAT(first, ' ', last) AS receiver_name "
. 'FROM names '
. 'GROUP BY last, first';
if ($result = $mysqli->query($sql)) {
$string = '';
$count = $result->num_rows;
$rows = $result->fetch_all();
for ($i = 0; $i < $count-1; $i++) {
$string .= $rows[$i][0] . ', ';
}
$string .= ' and ' . $rows[$i][0];
echo $string; // John Smith, Bob Dole, and George Bush
}
Nota ??strong> Este código assume que você sempre ter pelo menos 2 linhas retornadas. Tenho certeza que você pode descobrir como lidar com o caso de apenas um único nome retornado. :)
Outras dicas
SELECT GROUP_CONCAT(CONCAT_WS(' ', usrFirst, usrLast)) as receiver_name
FROM (
SELECT DISTINCT usr_first, usr_last
FROM mytable
) q
Esta solução irá distinguir entre 'Smith, John Davis'
e 'Davis Smith, John'
(retornará 'John Davis Smith'
duas vezes, não uma vez, uma vez que são pessoas diferentes).