4 votes

MySQL Comment retourner des résultats uniques/distincts?

Je lance la requête MySQL suivante pour trouver les voitures qui n'ont pas de manuels (et qui ont des roues noires, etc.)

SELECT `cars`.* FROM `cars`
INNER JOIN wheels ON cars.id = wheels.car_id
LEFT OUTER JOIN manuals ON cars.id = manuals.car_id
WHERE (cars.created_at > '2010-09-09'
AND wheels.color = 'Black'
AND wheels.created_at < '2011-01-05'
AND manuals.car_id IS NULL)

Les résultats de la requête semblent corrects, mais la voiture avec l'identifiant 27 est retournée deux fois. Comment puis-je modifier la requête pour que tous les résultats soient uniques (pas de doublons) ?

15voto

Vous pourriez essayer SELECT DISTINCT au lieu de SELECT

5voto

Octopus-Paul Points 4290

Ajouter group by cars.id à la fin de la requête EG:

SELECT `cars`.* FROM `cars`
INNER JOIN wheels ON cars.id = wheels.car_id
LEFT OUTER JOIN manuals ON cars.id = manuals.car_id
WHERE (cars.created_at > '2010-09-09'
    AND wheels.color = 'Black'
    AND wheels.created_at < '2011-01-05'
    AND manuals.car_id IS NULL)
GROUP BY cars.id

3voto

bernie Points 44206

En supposant que cars.id est une clé primaire unique, l'une de ces jointures provoque le produit cartésien. Autrement dit : soit wheels soit manuals contiennent plus d'une correspondance pour cars.id = 27.

Les sous-interrogations sont souvent un bon outil pour éliminer les produits cartésiens. La requête exemple ci-dessous montre deux méthodes d'utilisation des sous-interrogations.

  1. La première sous-interrogation garantit que nous ne regardons que les voitures avec des roues noires où cet enregistrement a été créé avant le 01/05/2011. La clause GROUP BY garantit que nous ne renvoyons qu'un seul enregistrement par w.car_id.

  2. La deuxième sous-interrogation (parfois appelée sous-interrogation corrélée) garantit qu'aucun manuel n'est trouvé pour chaque voiture dans la requête principale.

Non testé, mais transmet l'idée :

SELECT `cars.* 
  FROM `cars`
       JOIN (
           SELECT w.car_id
             FROM wheels w
            WHERE w.color = 'Black'
              AND w.created_at < '2011-01-05'
         GROUP BY w.car_id
       ) wheels 
       ON cars.id = wheels.car_id
WHERE 
    cars.created_at > '2010-09-09'
AND
    NOT EXISTS (SELECT m.car_id FROM manuals m WHERE m.car_id = cars.id)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X