MySQL: uso no válido de la función de grupo

104

Estoy usando MySQL. Aquí está mi esquema:

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

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

Catálogo ( sid: integer, pid: integer , cost: real)

(las claves principales están en negrita)

Estoy tratando de escribir una consulta para seleccionar todas las piezas fabricadas por al menos dos proveedores:

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

En primer lugar, ¿estoy haciendo esto de la manera correcta?

En segundo lugar, obtengo este error:

1111 - Uso no válido de la función de grupo

¿Qué estoy haciendo mal?

Nick Heiner
fuente

Respuestas:

173

Necesitas usar HAVING, no WHERE.

La diferencia es: la WHEREcláusula filtra qué filas selecciona MySQL. Luego, MySQL agrupa las filas y agrega los números para su COUNTfunción.

HAVINGes como WHERE, solo sucede después deCOUNT que se ha calculado el valor, por lo que funcionará como espera. Reescribe tu subconsulta como:

(                  -- 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)
rjh
fuente
25
Además, si se usa GROUP BY, HAVING debe ser posterior a GROUP BY
Viacheslav
1
Además, GROUP BY debe ser antes de TENER .... Debería haber leído el comentario de Bandolero: D
Andrew
8

Primero, el error que está obteniendo se debe a dónde está usando la COUNTfunción; no puede usar una función agregada (o de grupo) en la WHEREcláusula.

En segundo lugar, en lugar de utilizar una subconsulta, simplemente une la tabla a sí misma:

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

Lo que creo que debería devolver solo filas donde existen al menos dos filas con lo mismo pidpero hay al menos 2 sids. Para asegurarse de que obtenga solo una fila por pid, he aplicado una cláusula de agrupación.

Mark Elliot
fuente
¿Es posible que ni siquiera necesite unirme? (vea mi respuesta actualizada, donde proporcioné una posible solución).
Nick Heiner
@Rosarch, creo que querrá usarlo COUNT(DISTINCT sid)en su consulta actualizada.
Mark Elliot
No sidsiempre tendría que ser distinto de todos modos, porque sidy pidjuntos forman una clave primaria para Catalog?
Nick Heiner