MySQL: utilisation non valide de la fonction de groupe


105

J'utilise MySQL. Voici mon schéma:

Fournisseurs ( sid: entier , sname: chaîne, chaîne d'adresse)

Parts ( pid: integer , pname: string, color: string)

Catalogue ( sid: entier, pid: entier , coût: réel)

(les clés primaires sont en gras)

J'essaie d'écrire une requête pour sélectionner toutes les pièces fabriquées par au moins deux fournisseurs:

-- Find the pids of parts supplied by at least two different suppliers.
SELECT c1.pid                      -- select the pid
FROM Catalog AS c1                 -- from the Catalog table
WHERE c1.pid IN (                  -- where that pid is in the set:
    SELECT c2.pid                  -- of pids
    FROM Catalog AS c2             -- from catalog
    WHERE c2.pid = c1.pid AND COUNT(c2.sid) >= 2 -- where there are at least two corresponding sids
);

Tout d'abord, est-ce que j'agis de la bonne manière?

Deuxièmement, j'obtiens cette erreur:

1111 - Utilisation incorrecte de la fonction de groupe

Qu'est-ce que je fais mal?

Réponses:


174

Vous devez utiliser HAVING, non WHERE.

La différence est la suivante: la WHEREclause filtre les lignes sélectionnées par MySQL. Ensuite, MySQL regroupe les lignes et agrège les nombres pour votre COUNTfonction.

HAVINGest comme WHERE, seulement cela se produit après que la COUNTvaleur a été calculée, donc cela fonctionnera comme vous le souhaitez. Réécrivez votre sous-requête comme:

(                  -- where that pid is in the set:
SELECT c2.pid                  -- of pids
FROM Catalog AS c2             -- from catalog
WHERE c2.pid = c1.pid
HAVING COUNT(c2.sid) >= 2)

25
De plus, si GROUP BY est utilisé, HAVING doit être après GROUP BY
— Viacheslav

1
De plus, GROUP BY doit être avant HAVING .... J'aurais dû lire le commentaire de Bandolero: D
— Andrew

9

Premièrement, l'erreur que vous obtenez est due à l'endroit où vous utilisez la COUNTfonction - vous ne pouvez pas utiliser une fonction d'agrégation (ou de groupe) dans la WHEREclause.

Deuxièmement, au lieu d'utiliser une sous-requête, joignez simplement la table à elle-même:

SELECT a.pid 
FROM Catalog as a LEFT JOIN Catalog as b USING( pid )
WHERE a.sid != b.sid
GROUP BY a.pid

Ce qui, je crois, ne devrait renvoyer que les lignes où au moins deux lignes existent avec le même pidmais il y a au moins 2 sids. Pour vous assurer de ne récupérer qu'une seule ligne par, pidj'ai appliqué une clause de regroupement.


Est-il possible que je n'ai même pas besoin d'une jointure? (voir ma réponse mise à jour, où j'ai fourni une solution possible.)
— Nick Heiner

@Rosarch, je pense que vous voudrez l'utiliser COUNT(DISTINCT sid)dans votre requête mise à jour.
— Mark Elliot

N'aurait-il pas sidtoujours besoin d'être distinct de toute façon, car sidet pidforment ensemble une clé primaire pour Catalog?
— Nick Heiner
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.