2017-10-13 15 views
0

Avoir à écrire une instruction select qui renvoie le nom, la ville et l'état de chaque fournisseur situé dans une ville et un état uniques. J'ai vu plusieurs threads similaires mais aucune des réponses données n'aide pour une raison quelconque. Mon code ne peut toujours pas renvoyer le nombre correct de résultats:Problèmes lors de la sélection de résultats uniques dans la sous-requête MySQL

Ecrivez une instruction select qui renvoie le nom, la ville et l'état de chaque fournisseur situé dans une ville et un état uniques. Il doit retourner 38 lignes.

/*problem 6*/ 

SELECT 
vendor_name, vendor_city, vendor_state 
FROM 
vendors 
WHERE 
vendor_city || vendor_state NOT IN (SELECT distinct 
     vendor_city || vendor_state 
    FROM 
     vendors 
    GROUP BY vendor_city, vendor_state having count(*)>1) 
ORDER BY vendor_state , vendor_city; 
+0

Votre sous-requête renvoie-t-elle des données correctes? –

+1

Tout ensemble de colonnes 'GROUP BY''d sera toujours unique, donc' DISTINCT' est superflue. Bien que dans une clause 'IN' les doublons ne feraient pas de différence de toute façon. La concaténation ('||') va ralentir les comparaisons - vous devriez pouvoir comparer les tuples: 'WHERE (vendor_city, vendor_state) NOT IN (...)'. Outre le contrôle de la sous-requête, comme teju l'a mentionné, quels résultats obtenez-vous? Trop de lignes, trop peu de lignes? Que se passe-t-il si vous inversez la colonne que vous commandez, est-ce que cela révèle quoi que ce soit? –

+0

Dans MySQL, l'opérateur '||' est synonyme de 'OR', pas de concaténation de chaîne. Si nous voulons une concaténation de chaînes, nous utilisons la fonction 'CONCAT()'. (Notez le cas de bordure avec concaténation, potentiel pour l'état correspondant = 'aa' ville = 'a' avec l'état = 'a' ville = 'aa', puisque la concaténation d'état et de ville donne la même valeur dans les deux cas. – spencer7593

Répondre

1

Cette requête doit satisfaire une interprétation possible de la spécification:

SELECT MIN(v.vendor_name) AS vendor_name 
     , v.vendor_city 
     , v.vendor_state 
    FROM vendors v 
    GROUP 
     BY v.vendor_city 
     , v.vendor_state 
    HAVING COUNT(*) = 1 

Cela devient le (city,state) tuples, et en comptant le nombre de lignes qui ont les mêmes valeurs, et l'exclusion de tout où plus d'une ligne a les mêmes valeurs. Parmi les lignes qui restent, il n'y aura qu'un seul nom vendeur à renvoyer.

(La spécification peut aussi être interprété différemment par exemple le même vendor_name dans plusieurs (city,state), et nous sommes désireux de retourner le vendor_name qui se produisent que dans une seule (city,state). Cela exigerait une autre requête.)


Une extension dans MySQL nous permet d'abandonner la fonction d'agrégat, si ONLY_FULL_GROUP_BY n'est pas inclus dans sql_mode à savoir nous pouvons remplacer MIN(v.vendor_name) avec juste v.vendor_name.

S'il y a une exigence que nous devons utiliser une requête imbriquée, je préférerais de beaucoup utiliser une vue en ligne pour retourner la "ville et l'état uniques", puis une opération de jointure.

SELECT t.vendor_name 
     , t.vendor_city 
     , t.vendor_state 
    FROM (SELECT v.vendor_city 
       , v.vendor_state 
      FROM vendors v 
      GROUP 
       BY v.vendor_city 
       , v.vendor_state 
      HAVING COUNT(*) = 1 
     ) u 
    JOIN vendors t 
     ON t.vendor_city <=> u.vendor_city 
    AND t.vendor_state <=> u.vendor_state 
    ORDER 
     BY t.vendor_name 
0

Il est généralement plus efficace de rechercher une réponse positive. Ainsi, au lieu de trouver ces fournisseurs qui ont plus que sur la ville/état (et puis utiliser pour ne pas inverser cela) faire l'inverse à l'avant et il suffit de chercher ceux qui ont une seule ville/état. Ensuite, utilisez une approche plus directe de la sortie finale en utilisant un inner join.

SELECT 
     v.vendor_name 
    , v.vendor_city 
    , v.vendor_state 
FROM vendors AS v 
INNER JOIN (
     SELECT 
      vendor_city 
      , vendor_state 
     FROM vendors 
     GROUP BY 
      vendor_city 
      , vendor_state 
     HAVING COUNT(*) = 1 
) AS d ON v.vendor_city = d.vendor_city 
     AND v.vendor_state = d.vendor_state 
ORDER BY v.vendor_state, v.vendor_city;