2010-02-25 3 views
70

Ich benutze MySQL. Hier ist mein Schema:MySQL: Ungültige Verwendung der Gruppenfunktion

Lieferanten (sid: integer, sname: string, Adresse string)

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

Katalog (sid: integer, pid: integer, Kosten: real)

(Primärschlüssel bolded sind)

ich bin t rocknung eine Abfrage zu schreiben, alle Teile auszuwählen, die von mindestens zwei Lieferanten hergestellt werden:

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

Zunächst einmal bin ich sogar darüber auf den richtigen Weg?

Zweitens bekomme ich diesen Fehler:

1111 - Invalid use of group function

Was mache ich falsch?

Antwort

120

Sie müssen HAVING verwenden, nicht WHERE.

Der Unterschied ist: Die WHERE-Klausel filtert, welche Zeilen MySQL auswählt. Dann MySQL gruppiert die Zeilen zusammen und aggregiert die Zahlen für Ihre COUNT-Funktion.

HAVING ist wie WHERE, nur passiert es nach der COUNT Wert wurde berechnet, so wird es funktionieren, wie Sie erwarten. Schreiben Sie Ihre Unterabfrage wie folgt um:

(     -- 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) 
+1

Also 'HAVING' zählt zuerst dann filtert, ist das richtig? –

+15

Auch wenn GROUP BY verwendet wird, sollte HAVING nach GROUP BY – Viacheslav

+0

sein. Außerdem muss GROUP BY vor HAVING sein .... Sollte Bandoleros Kommentar gelesen haben: D – Andrew

4

Erstens, der Fehler, den Sie bekommen, liegt daran, wo Sie die COUNT Funktion verwenden - Sie können keine Aggregatfunktion (oder Gruppenfunktion) in der WHERE Klausel verwenden.

Zweitens stattdessen eine Unterabfrage zu verwenden, verbinden Sie einfach die Tabelle mit sich selbst:

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

die ich glaube, sollte nur Zeilen zurück, wo mindestens zwei Reihen existieren mit dem gleichen pid aber es gibt mindestens 2 sid s. Um sicherzustellen, dass Sie nur eine Zeile pro pid erhalten, habe ich eine Gruppierungsklausel angewendet.

+0

Ist es möglich, dass ich nicht einmal eine Verbindung benötige? (Siehe meine aktualisierte Antwort, wo ich eine mögliche Lösung geliefert habe.) –

+0

@Rosarch, ich denke, Sie wollen 'COUNT (DISTINCT sid)' in Ihrer aktualisierten Abfrage verwenden. –

+0

Müsste 'sid' nicht immer anders sein, weil' sid' und 'pid' zusammen einen Primärschlüssel für' Catalog' bilden? –

Verwandte Themen