deve aparecer na cláusula GRUPO POR GRUPO ou ser usado em uma função agregada
Eu tenho uma mesa que se parece com este chamador 'makerar'
cname | wmname | avg
--------+-------------+------------------------
canada | zoro | 2.0000000000000000
spain | luffy | 1.00000000000000000000
spain | usopp | 5.0000000000000000
E eu quero seleccionar a avg máxima para cada nome.
SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname;
mas eu vou ter um erro,
ERROR: column "makerar.wmname" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname;
então eu faço isto
SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname, wmname;
No entanto, isto não dará os resultados pretendidos, e a saída incorreta abaixo é mostrada.
cname | wmname | max
--------+--------+------------------------
canada | zoro | 2.0000000000000000
spain | luffy | 1.00000000000000000000
spain | usopp | 5.0000000000000000
Os Resultados Reais devem ser
cname | wmname | max
--------+--------+------------------------
canada | zoro | 2.0000000000000000
spain | usopp | 5.0000000000000000
Como posso resolver este problema?
Nota: Esta tabela é uma VIEW criada a partir de uma operação anterior.
239
3
Sim, este é um problema comum de agregação. Antes de SQL3 (1999), os campos selecionados devem aparecer na cláusula
GROUP BY
[*].Para resolver esta questão, você deve calcular o agregado em uma subconsulta e então juntar-se a ela para obter as colunas adicionais que você'd precisa mostrar:
Mas você também pode usar funções de janela, que parecem mais simples:
A única coisa com este método é que ele mostrará todos os registros (as funções de janela não agrupam). Mas ele mostrará o correto (ou seja, máximo no nível
cname
)MAX
para o país em cada linha, então ele's depende de você:A solução, indiscutivelmente menos elegante, para mostrar o único
(cname, wmname)
tuples que corresponde ao valor máximo, é:[*]: Curiosamente, mesmo que a especificação permita seleccionar campos não agrupados, os motores principais parecem não gostar muito. Oracle e SQLServer apenas don't permitem isso de forma alguma. Mysql costumava permitir isso por padrão, mas agora desde 5.7 o administrador precisa habilitar essa opção (
ONLY_FULL_GROUP_BY
) manualmente na configuração do servidor para que esse recurso seja suportado...Em Postgres, você também pode utilizar a sintaxe especial
DISTINCT ON (expressão)
:Utilizando
rank()
window function:**Nota***
Qualquer um deles irá preservar múltiplos valores máximos por grupo. Se você quiser apenas um registro por grupo, mesmo que haja mais de um registro com avg igual a max você deve verificar @ypercube's resposta.