Dúvida com MAX( )

Galera, eu estava com um problema com o group by e consegui o resultado esperado com o MAX( ).
Pelo que vi, o MAX retorna o maior valor, logicamente falando, o select abaixo pode ter “erros” de consulta ou pode acontecer de não mostrar alguns dados na consulta??

Motivo de eu usar o MAX: Quero agrupar colunas e essa foi a única forma que encontrei.
Por enquanto estar tudo certo, mas estou meio desconfiado se estou usando o MAX corretamente.

Aguardo a opinião de vocês.

Esse é o meu select:

SELECT
MAX(IDPRODUTOS) as idProduto ,
SUM(qtd) as qtd ,
Max(ValorPago)as ValorPago,
Max(codInterno)as codInterno,
Max(Descricao)as Descricao,
round (SUM(ValorPago), 2) AS Preco_total,
Max( CodBarras)as CodBarras,
Max(Preco)as Preco,
Max( Estoque)as Estoque
FROM vendas
LEFT JOIN produtos
ON vendas.IDprodutos = produtos.codInterno
where DataVenda ='11.12.2016'
group by IDPRODUTOS
order by qtd DESC

Correto deve estar, codInterno é provavelmente único na tabela de produtos.

Repare porém, que você está agrupando vendas por produto, e nao os produtos em si.
Ou seja, você pode usar essa abordagem:

  SELECT <colunas que você quer diretamente>
  FROM 
  (
    SELECT idProdutos, SUM(qtd) qtd, SUM(ValorPago) valor pago
    FROM vendas
    GROUP BY 
      idProdutos
  ) v
  LEFT JOIN produtos
  ON idProdutos = codInterno

Isso deve te gerar um plano de execuçao mais eficiente (imagino, só rodando mesmo para saber).

Vou testar esse select e posto resultado.

Olá Igor,

infelizmente não consegui entender bem o que de fato tu querias utilizar o MAX ou apenas o SUM.

Olhando aqui achei um erro

o correto seria colocar no group by TODAS as colunas que não possuem uma função, ou seja, levando em conta que tu querias apenas usar o SUM() ficaria mais ou menos assim:

SELECT
IDPRODUTOS as idProduto ,
SUM(qtd) as qtd ,
ValorPago,
codInterno,
Descricao,
round (SUM(ValorPago), 2) AS Preco_total,
CodBarras,
Preco,
Estoque
FROM vendas
LEFT JOIN produtos
ON vendas.IDprodutos = produtos.codInterno
where DataVenda ='11.12.2016'
group by  idProduto, ValorPago, codInterno, Descricao, CodBarras, Preco, Estoque
order by qtd DESC

Usei o MAX apenas por que foi a unica forma que encontrei para agrupar.
Mas por favor, me explique isso, pq vc colocou todas essas colunas no group by, sendo que quero agrupar apenas por uma coluna ?
Por exemplo:

group by idProduto, ValorPago, codInterno, Descricao, CodBarras, Preco, Estoque
Como sei por qual delas estou agrupando?
Caso eu queria escolher a coluna Descricao, como ficaria?

Como sempre usei o MySql, sempre coloquei apenas uma coluna.
Estou há vários dias atrás dessa resposta.
Aguardo, abraços.

Oi igor,

peço desculpas pois acho que não entendi a relação entre as tabelas e se existem chaves primárias, mas estou tentando lhe ajudar.

Fiz um pequeno banco para testar com uma consulta

Usei o group by deste maneira pois segundo a própria W3C (http://www.w3schools.com/sql/sql_groupby.asp):

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name; 

Vai no Group By as colunas que não estão em uma função de agregação.

Entendi, vai no group by as colunas que não estão em uma função de agregação.
Mas o que está me deixando confuso é o pq de mais de 1 coluna no group by.

Exemplo:
GROUP BY Coluna1, Coluna2
Como sei por qual está agrupando?
E se eu quiser agrupar só pela coluna1 ou só pela coluna2?

Usei o max pq com ele eu posso colocar só a coluna que eu quero no Group by.

Tu até podes agrupar por uma coluna específica, mas veja o exemplo:

Minha tabela possui estas colunas com estes dados:
produto_id | preco | descricao              | estoque
1                | 10      | Maquina de Lavar |10
1                | 20      | Maquina de lavar  | 23

Então, fiz a seguinte seleção:

Exemplo 1:

SELECT produto_id, sum(estoque), preco FROM produtos GROUP by produto_id
Resultado:
produto_id | sum(estoque) | preco
1                | 33                   | 10

Como você pode ver, não incluí o preço dentro do Group By, ele fez corretamente a soma do estoque mas retornou apenas 1 linha com preco do primeiro produto cadastrado.

Exemplo 2:

Já, se eu adiciono o preço ele retorna a linha sem fazer a soma pois não existe nenhum produto que possua o mesmo produto_id com o mesmo valor de preco.

Dei aquele exemplo de todas juntas pois eu não tinha entendido bem qual era o retorno de consulta que querias;

Exemplo 3:

Podes até fazer o SELECT e passar no Group By uma coluna que você não está selecionando:
SELECT sum(estoque), preco FROM produtos GROUP by produto_id
Resposta:
sum(estoque)| preco
33                  |10

Tudo depende do resultado de consulta que queres e se há valores que “batem” com a sua pesquisa. (Como mostra o Exemplo 2).

Tentei ser abrangente e claro mas não sei se consegui hahahah.
Qualquer coisa pergunte mais!
(Desculpa não mandar vários prints, mas sou user novo e só posso postar um por resposta :confused: )
Abraço

Acho que agora chegamos ao ponto, se funcionasse como no seu exemplo, estaria ótimo.
Peguei uma tabela aqui pra te mostrar, o erro está nas colunas que estão no GROUP BY veja:

Se usar assim, funciona:
SELECT codInterno, sum(estoque), preco FROM produtos GROUP by codInterno, preco;

Se eu usar assim, dá erro:
SELECT codInterno, sum(estoque), preco FROM produtos GROUP by codInterno;
ERRO: Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause).

Quero exatamente como que vc mostrou, porém não funciona dessa forma aqui.
uso o firebird 2.5.

Olá Igor,

estes meus testes funcionaram porque fiz com o MySQL (não sabia qual SGBD estavas usando) testei com o Postgre e obtive o mesmo erro que você.

Das duas uma:
1 - Seguir usando como está (apesar de não ser a melhor maneira)

2 - Me explicar um pouco mais qual é o objetivo por trás deste SQL. O que estavas tentando buscar com ele? É necessário que seja realizado em um único comando? Para que possamos melhorar ele juntos

O que preciso é que ele agrupe por um campo.
Da mesma forma que vc mandou, mas acho que não funciona dessa forma no firebird nem no postgre.

O motivo de eu sair do Mysql é pq eu penso em algum dia vende-lo e tem uma licença do Mysql que impede fazer isso, vc acha que daria algum problema pra mim ou para o cliente caso eu venda esse software feito em Java + Mysql ?

Olha, nunca cheguei ao ponto de comercializar um software que fiz, não sei te dizer.

O que tu podes fazer para ajudar nessa consulta é talvez fazer ela em mais um passo. Buscar as somas que tu precisa em uma Query e se possível buscar os próximos dados em outra…

Pode me dá um exemplo de como eu separaria as consultas?

Claro, vamos resolver isto.

Tens como me explicar quais colunas tu queres pegar, porque tu queres ela, qual o objetivo dessa consulta? Onde ela seria usada?

Ele será usada para um relatório do JasperSoft, mas só estou conseguindo montar o select.

Esse select funciona no mysql, o que eu quero é fazer um desse que gere o mesmo resultado no firebird ou postgre:

Quero as colunas abaixo:

SELECT
IDProdutos ,
SUM(qtd) as qtd ,
ValorPago,
codInterno,
Descricao,
round (SUM(ValorPago), 2) AS Preco_total,
CodBarras,
Preco,
Estoque
FROM vendas
LEFT JOIN produtos
ON vendas.IDprodutos = produtos.codInterno
where DataVenda ='2017-01-05’
group by IDPRODUTOS
order by qtd DESC

Preciso saber o que mudar para isso rodar no firebird ou postgre.

Valeu pela força.

Olá Igor,

lembras deste exemplo?

para este caso, poderías fazer o seguinte:

SELECT codInterno, sum(estoque) FROM produtos GROUP by codInterno;
SELECT codInterno, preco FROM produtos;
Obtendo tanto a soma do estoque como o preco, mas sei que o que queres é um pouco mais complexo.

Poderias me informar quais dessas colunas são da tabela de vendas e quais são da tabela produto?

Terias o modelo ER deste banco? (podes me mandar em privado caso não queiras publicar aqui)

Desculpa estar te enchendo de perguntas, mas estou tentando entender melhor a tua implementação para podermos montar a melhor solução, por exemplo não estou entendendo o motivo de um LEFT JOIN.

Pode perguntar, sem problemas, assim é mais fácil chegar a solução.
Então:
Tabela Vendas:
IDProdutos
qtd
ValorPago
DataVenda

Tabela Produtos:
CodInterno
Descricao
Preco
Estoque
CodBarras

Motivo do left join: Na tabela de Vendas tem o ID do produto, a partir desse ID ela buscar em Produtos o nome, estoque, preco, codBarras e codInterno(Aqui fica o valor que não se repete)

E o modelo ER, eu não tenho, ainda sou novo nessa área de DB e fui apenas criando as colunas.
Mas vou pesquisar sobre.

Pra ficar mais fácil de ver:

SELECT
**vendas.**IDProdutos ,
SUM(**vendas.**qtd) as qtd ,
**vendas.**ValorPago,
**produtos.**codInterno,
**produtos.**Descricao,
round (SUM(**vendas.**ValorPago), 2) AS Preco_total,
**produtos.**CodBarras,
**produtos.**Preco,
**produtos.**Estoque
FROM vendas
LEFT JOIN produtos
ON **vendas.**IDprodutos = **produtos.**codInterno
where **vendas.**DataVenda ='2017-01-05’
group by **vendas.**IDPRODUTOS
order by **vendas.**qtd DESC

@Igor_Lisboa, você testou o primeiro exemplo que postei aqui?

Testei, o select funciona, mas não agrupa.
você usa o firebird ou postgre ?

O que você quer dizer com nao agrupa?

Dá um exemplo (com dados) do que você quer usando esse site: http://sqlfiddle.com/