MySQL: uso non valido della funzione di gruppo


104

Sto usando MySQL. Ecco il mio schema:

Fornitori ( sid: integer , sname: string, address string)

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

Catalogo ( sid: intero, pid: intero , costo: reale)

(le chiavi primarie sono in grassetto)

Sto cercando di scrivere una query per selezionare tutte le parti realizzate da almeno due fornitori:

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

Prima di tutto, sto anche affrontando questo nel modo giusto?

In secondo luogo, ottengo questo errore:

1111 - Uso non valido della funzione di gruppo

Che cosa sto facendo di sbagliato?

Risposte:


173

Devi usare HAVING, no WHERE.

La differenza è: la WHEREclausola filtra le righe selezionate da MySQL. Quindi MySQL raggruppa le righe e aggrega i numeri per la tua COUNTfunzione.

HAVINGè come WHEREse accade solo dopo che il COUNTvalore è stato calcolato, quindi funzionerà come previsto. Riscrivi la tua sottoquery come:

(                  -- 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
Inoltre, se si utilizza GROUP BY, HAVING dovrebbe essere dopo GROUP BY
Viacheslav

1
Inoltre, GROUP BY deve essere prima di HAVING .... Avrebbe dovuto leggere il commento di Bandolero: D
Andrew

8

Innanzitutto, l'errore che ricevi è dovuto a dove stai usando la COUNTfunzione: non puoi usare una funzione aggregata (o di gruppo) nella WHEREclausola.

In secondo luogo, invece di utilizzare una sottoquery, unisci semplicemente la tabella a se stessa:

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

Che credo dovrebbe restituire solo righe in cui esistono almeno due righe con lo stesso pidma ci sono almeno 2 sids. Per essere sicuro di recuperare solo una riga per ogni pidho applicato una clausola di raggruppamento.


È possibile che non abbia nemmeno bisogno di iscriversi? (vedi la mia risposta aggiornata, dove ho fornito una possibile soluzione.)
Nick Heiner

@ Rosarch, penso che vorrai utilizzare COUNT(DISTINCT sid)nella tua query aggiornata.
Mark Elliot

Non sarebbe comunque sidsempre necessario essere distinti, perché side pidinsieme formano una chiave primaria per Catalog?
Nick Heiner
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.