MySQL: uso inválido de função de grupo


104

Estou usando o MySQL. Aqui está meu esquema:

Fornecedores ( sid: inteiro , sname: string, string de endereço)

Partes ( pid: inteiro , pname: string, cor: string)

Catálogo ( sid: inteiro, pid: inteiro , custo: real)

(as chaves primárias estão em negrito)

Estou tentando escrever uma consulta para selecionar todas as peças feitas por pelo menos dois fornecedores:

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

Em primeiro lugar, estou mesmo fazendo isso da maneira certa?

Em segundo lugar, recebo este erro:

1111 - Uso inválido de função de grupo

O que estou fazendo de errado?

Respostas:


173

Você precisa usar HAVING, não WHERE.

A diferença é: a WHEREcláusula filtra quais linhas o MySQL seleciona. Então o MySQL agrupa as linhas e agrega os números para sua COUNTfunção.

HAVINGé como WHERE, só acontece depois que o COUNTvalor foi calculado, então vai funcionar como você espera. Reescreva sua 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)

25
Além disso, se GROUP BY for usado, HAVING deve ser após GROUP BY
Viacheslav

1
Além disso, GROUP BY precisa ser antes de TER .... Deveria ter lido o comentário de Bandolero: D
Andrew

8

Primeiro, o erro que você está obtendo é devido ao local em que você está usando a COUNTfunção - você não pode usar uma função de agregação (ou grupo) na WHEREcláusula.

Em segundo lugar, em vez de usar uma subconsulta, simplesmente junte a tabela a ela mesma:

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

O que eu acredito que deva retornar apenas linhas onde existem pelo menos duas linhas com o mesmo, pidmas há pelo menos 2 sids. Para ter certeza de que você receberá de volta apenas uma linha, pidapliquei uma cláusula de agrupamento.


É possível que eu nem precise de um cadastro? (veja minha resposta atualizada, onde forneci uma solução possível.)
Nick Heiner

@Rosarch, acho que você vai querer usar COUNT(DISTINCT sid)em sua consulta atualizada.
Mark Elliot

Nem sidsempre teria que ser distinto de qualquer maneira, porque side pidjuntos formam uma chave primária para Catalog?
Nick Heiner
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.