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.