Pergunta

Tudo o que vi até agora é remover as entradas duplicadas em um banco de dados automaticamente. Eu quero enfatizar no início disso que Não há dados duplicados no banco de dados. Também começarei com o fato de ainda estar aprendendo muito sobre o design, normalização, relacionamentos, e, acima de tudo, SQL!

Eu tenho uma tabela de clientes, com um clientID (pk) e um client_name. Eu tenho uma tabela de funções, com um Roleid (PK) e um Role_name. Qualquer cliente pode ter várias funções associadas a ele. Por isso, criei uma tabela client_role_link, com ClientID e Roleid como os dois campos. Então eu corro isto:

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')

Então, digamos que eu tenha um cliente que tenha duas funções associadas a ele (funções '1' e '2'). Esta consulta retorna duas linhas, uma para cada função. Quando eu recuperar esses resultados, estou usando um while loop para percorrer os resultados e produzi -los em um <select> Lista. Então está causando dois <option>S com o mesmo cliente listado.

Eu entendo por que minha consulta está retornando duas linhas, faz sentido. Então, aqui vem a pergunta duas vezes:

  1. Existe um design de banco de dados/tabela melhor que eu deveria estar usando ou uma consulta mais otimizada?
  2. Ou isso é algo que eu devo lidar no PHP? Em caso afirmativo, existe uma solução mais elegante que adicionar todos os resultados em uma matriz e depois voltar pela matriz e remover duplicatas?

Pensamentos?

Foi útil?

Solução

Se você quiser mostrar as duas funções, sua consulta é OK.

MySQL não suporta tipos de dados da matriz, então você deve preencher uma matriz associativa no PHP lado usando o ResultSet com os nomes de clientes duplicados.

Se você só precisar mostrar aos clientes que têm uma das funções, use esta consulta:

SELECT  c.*
FROM    client c
WHERE   c.clientid IN
        (
        SELECT  roleid
        FROM    client_role_link crl
        WHERE   crl.roleid IN (1, 2)
        )

Isso retornará um registro por cliente, mas não mostrará nenhum papel.

A terceira maneira implodiria os nomes de função no lado do 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

e explodi -los PHP lado, mas verifique se os nomes de função não se misturam com o separador.

Outras dicas

Você poderia usar mysql_fetch_assoc () Para recuperá -los em forma de matriz. Então você poderia ter algo como código não testado, mas pode 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
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top