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.