MySQL GROUP_CONCAT: formateando la salida
-
06-07-2019 - |
Pregunta
Actualmente tengo la siguiente consulta:
SELECT group_concat(DISTINCT usrFirst, usrLast) as receiver_name //etc
Cuando uso PHP, genera mi lista de nombres de la siguiente manera:
<?php
echo $row['receiver_name'];
//Outputs: JohnDoe,BillSmith,DaveJones
//Desired output: John Doe, Bill Smith, and Dave Jones
Necesito ayuda para descubrir tres cosas:
-
¿Cómo puedo poner un espacio entre el nombre y el apellido?
-
¿Cómo se puede insertar un espacio después de cada coma?
-
¿Cómo puedo agregar un 'y' justo antes de que se muestre el apellido?
Solución
No estoy seguro de que debas intimidar a MySQL para que haga exactamente lo que quieres allí. Sugeriría usar lo siguiente:
SELECT DISTINCT CONCAT(first, ' ', last) AS receiver_name
FROM names;
Luego recorra este conjunto de resultados en PHP y maneje el caso de 'y' allí.
Si el rendimiento es una preocupación (harás esta consulta a menudo). Se beneficiaría de no usar DISTINCT en el valor calculado de CONCAT (primero, '', último) ya que eso requeriría el uso de una tabla temporal.
Para ajustarlo, agregue el siguiente índice:
ALTER TABLE names ADD INDEX (last, first);
Y cambie su consulta de la siguiente manera:
SELECT CONCAT(first, ' ', last) AS receiver_name
FROM names
GROUP BY last, first;
Podrá obtener sus valores directamente del índice sin recurrir a una tabla temporal o clasificador de archivos.
En lo que respecta al bucle, algo como lo siguiente funcionaría:
<?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 Este código asume que siempre tendría al menos 2 filas devueltas. Estoy seguro de que puede descubrir cómo manejar el caso de un solo nombre devuelto. :)
Otros consejos
SELECT GROUP_CONCAT(CONCAT_WS(' ', usrFirst, usrLast)) as receiver_name
FROM (
SELECT DISTINCT usr_first, usr_last
FROM mytable
) q
Esta solución distinguirá entre 'Smith, John Davis'
y 'Davis Smith, John'
(devolverá 'John Davis Smith'
dos veces, no una vez, ya que son personas diferentes).