2012-07-10 30 views
5

Tengo un problema con la implementación de un módulo donde uno project puede pertenecer a múltiples categories. Ejemplo: proyecto "Programador PHP" pertenece a las categorías: Programación, PHP.MySQL LEFT JOIN duplica los resultados

Suponiendo que la siguiente consulta (seleccionan los proyectos que pertenecen a categorías 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'` 

consigo un mismo proyecto regresó dos veces, porque hay 2 partidos en la mesa para el project_id = 94

tabla projects_category esquema:

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

¿E-cando algo?

Solución: utilizar GROUP BY o DISTINCT

+1

Si solo quiere uno de cada proyecto, añada 'GROUP BY project_id' a su consulta – mariusnn

+0

@mariusnn gracias, ¡funciona! – technology

+0

No usar agrupar, ver mi explicación – Sebas

Respuesta

8

No, esto está muy bien. Este es solo uno de los pocos casos en los que desea utilizar la palabra clave DISTINCT para eliminar duplicados.

En este caso, esto se justifica por el hecho de que la lógica de la consulta es correcta, aunque devuelva más de una fila. Muchas veces se puede ver el uso de DISTINCT cuando en realidad la lógica de la consulta es incorrecta.

Side-nota:

  • cualquier filtro en una tabla de referencia que está utilizando en la cláusula WHERE que no sea IS NULL/IS NOT NULL haría cualquier LEFT JOIN en este mismo turno referencia a una tabla INNER JOIN, como para el conjunto de resultados finales comportamiento. (Ver esto: https://stackoverflow.com/a/15483895/1291428)
  • que no conviene utilizar GROUP BY para simular el efecto de DISTINCT, por 2 razones:

    1/Esto no es sólo el propósito. Uno de los efectos de GROUP BY es eliminar duplicados, pero su propósito principal es agrupar filas de acuerdo con un cierto conjunto de criterios, a fin de aplicar algunos cálculos/operaciones analíticas sobre ellos.

    2/GROUP BY también ORDER BY los resultados (en mysql), que no es necesariamente lo que quiere y en ese caso ralentiza la ejecución. Por favor, solo asegure el uso apropiado de lo que los motores están proporcionando, eso siempre es mejor desde el punto de vista de la compatibilidad con versiones anteriores. (Anticipando que lo que incluye como otorgado no es en realidad)

respetos.

+0

bueno, no sabía que ... el grupo Tought por era un sinónimo de DISTINCT. Gracias, ahora estoy usando distinct y funciona genial :) – technology

+0

Tanques para aclarar un punto acerca de DISTINCT y GROUP BY – mariusnn

0

También puede reescribir esto como una "IN" para moverse por duplicados:

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' 

El "en" impide la formación de duplicados cuando se utiliza une para filtrar registros.