2012-07-10 19 views
5

Ho un problema con l'implementazione di un modulo in cui uno project può appartenere a più categories. Esempio: il progetto "Programmatore PHP" appartiene alle categorie: Programmazione, PHP.MySQL LEFT JOIN duplicati risultati

Assumendo la seguente query (selezionare i progetti che appartengono a categorie 1,3,11):

SELECT projects.* FROM projects 
    LEFT JOIN pojects_category on projects.id = pojects_category.project_id 
    WHERE pojects_category.category_id IN (1,3,11) and projects.id='94'` 

ottengo un l'stesso progetto è tornato due volte, perché ci sono partite la tavola per la project_id = 94

tabella projects_category schema:

CREATE TABLE IF NOT EXISTS `pojects_category` (
    `project_id` int(10) NOT NULL, 
    `category_id` int(10) NOT NULL, 
    KEY `category_id` (`category_id`), 
    KEY `project_id` (`project_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 


INSERT INTO `pojects_category` (`project_id`, `category_id`) VALUES 
(94, 3), 
(94, 1); 

Mi manca qualcosa?

Soluzione: utilizzare GROUP BY o DISTINCT

+1

Se si desidera solo uno di ciascun progetto, aggiungere 'GROUP BY project_id' alla query – mariusnn

+0

@mariusnn grazie, funziona! – technology

+0

Non usare group by, vedere la mia spiegazione – Sebas

risposta

8

No, questo va bene. Questo è solo uno dei rari casi in cui si desidera utilizzare la parola chiave DISTINCT per rimuovere i duplicati.

In questo caso ciò è giustificato dal fatto che la logica della query è corretta, anche se restituisce più di una riga. Molte volte si può vedere l'uso di DISTINCT quando in realtà la logica della query è sbagliata.

Side-nota:

  • qualsiasi filtro su un riferimento tavolo che si sta utilizzando nella clausola WHERE diverso IS NULL/IS NOT NULL avrebbe alcun LEFT JOIN su questo stesso turno di riferimento tabella in un INNER JOIN, come per il gruppo di risultati finale comportamento. (Vedi questo: https://stackoverflow.com/a/15483895/1291428)
  • non dovrebbe utilizzare GROUP BY per simulare l'effetto di DISTINCT, per 2 motivi:

    1/Questo non è solo lo scopo. Uno degli effetti di GROUP BY consiste nell'eliminare i duplicati, ma il suo scopo principale è raggruppare le righe in base a un determinato insieme di criteri, al fine di applicare alcuni calcoli/operazioni analitici su di essi.

    2/GROUP BY anche ORDER BY i risultati (in mysql), che non è necessariamente quello che si desidera e in tal caso rallenta l'esecuzione. Per favore, basta garantire un uso appropriato di ciò che i motori stanno fornendo, che è sempre meglio dal punto di vista della compatibilità diretta. (Anticipando che ciò che si include come concesso non è in realtà)

saluti.

+0

beh, non sapevo che ... ho insegnato gruppo era sinonimo di DISTINCT. Grazie, ora sto usando distinto e funziona benissimo :) – technology

+0

Serbatoi per fare un punto chiaro su DISTINCT e GROUP BY – mariusnn

0

Si può anche riscrivere questo come un "IN" per aggirare i duplicati:

SELECT projects.* 
FROM projects  
where projects.id in (select project_id 
         from projects_category 
         WHERE pojects_category.category_id IN (1,3,11) 
        ) and 
     projects.id='94' 

Il "in" impedisce duplicati la formazione quando si utilizza unisce per i record di filtraggio.