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.