Uno de muchas filas duplicadas mesa de enlace que causan devueltos
-
18-09-2019 - |
Pregunta
Todo lo que he visto hasta el momento se trata de la eliminación de entradas duplicadas en una base de datos de forma automática. Quiero hacer hincapié en el principio de este que no hay datos duplicados en la base de datos. También voy a empezar con el hecho de que mucho todavía estoy aprendiendo sobre el diseño de RDBMS, la normalización, las relaciones y, sobre todo, SQL!
Tengo una tabla de clientes, con un ClientID (PK) y un client_name. Tengo una tabla de funciones, con un roleid (PK) y un ROLE_NAME. Cualquier cliente puede tener varios roles asociados con ella. Así que creé una mesa client_role_link, con ClientID y roleid como los dos campos. Luego ejecutar esto:
SELECT client.client_name, role.role_name FROM client
LEFT JOIN client_role_link ON client_role_link.clientid=client.clientid
LEFT JOIN role ON client_role_link.roleid=role.roleid
WHERE (role.roleid='1' OR role.roleid='2')
Así que vamos a decir que tengo un cliente que tiene dos roles asociados a ella (papeles '1' y '2'). Esta consulta devuelve dos filas, una para cada función. Cuando llego a estos resultados respaldan que estoy usando un bucle while
para pasar por los resultados y salida de ellos, en una lista <select>
. A continuación, está causando dos de <option>
con el mismo cliente que se indican.
entiendo por qué mi consulta devuelve dos filas, tiene sentido. Así que aquí viene la pregunta dos veces:
- ¿Hay un mejor diseño de base de datos / tabla que debo utilizar, o una consulta más optimizado?
- O es esto algo que debe manejar en el PHP? Si es así, ¿hay una solución más elegante que la adición de todos los resultados en una matriz, a continuación, un bucle de vuelta a través de la matriz y la eliminación de duplicados?
Los pensamientos?
Solución
Si desea mostrar los dos papeles, a continuación, su consulta es OK
.
MySQL
no soporta tipos de datos de la matriz, por lo que debe llenar una matriz asociativa en el lado PHP
usando el conjunto de resultados con los nombres de clientes duplicados.
Si sólo tiene que mostrar a los clientes que tengan una de las funciones, utilice esta consulta:
SELECT c.*
FROM client c
WHERE c.clientid IN
(
SELECT roleid
FROM client_role_link crl
WHERE crl.roleid IN (1, 2)
)
Esto devolverá un registro por cliente, pero no mostrará ninguna función.
La tercera forma implosionaría los nombres de rol en el lado del servidor:
SELECT c.*, GROUP_CONCAT(role_name SEPARATOR ';') AS roles
FROM client c
LEFT JOIN
client_role_link crl
ON crl.clientid = c.clientid
AND crl.roleid IN (1, 2)
LEFT JOIN
role r
ON r.roleid = crl.roleid
GROUP BY
c.id
y explotar ellos al otro lado PHP
, pero que seguro que los nombres de función no se mezclará con el separador.
Otros consejos
Se puede usar mysql_fetch_assoc () para conseguirlos de nuevo en forma de matriz. Posteriormente, se podría tener algo como código no probado, pero puede funcionar
$sql = "SELECT client.id, client.client_name, role.role_name FROM client LEFT JOIN client_role_link ON client_role_link.clientid=client.clientid LEFT JOIN role ON client_role_link.roleid=role.roleid WHERE (role.roleid='1' OR role.roleid='2')";
$result = mysql_query($sql);
$res = array();
while ($row = mysql_fetch_assoc($result)) {
$res[$row['id']]['roles'][] = $row['role_name'];
$res[$row['id']]['client_name'] = $row['client_name']; //you'll be overwriting each iteration probably a better way
}