Olá Marcelo,

> Ou será que é melhor fazer pela aplicação?

Nem a pau! Servidor não se chama servidor para mandar estação fazer conta.

Uma forma simples de aumentar consideravelmente o desempenho é trocando LEFT 
por INNER, mesmo que com isso teu SQL fique bem grande. Isso te poupará 
desses incômodos COALESCE e dos abomináveis OR na cláusula WHERE, além de 
permitir o uso de diversos índices simultaneamente, o que deve melhorar 
bastante o desempenho.

Sugiro algo como isso aqui:

select x.cod_id, x.nome, x.codigo, sum(x.qtd_itens) as qtd_itens, 
sum(x.qtd_balcao) as qtd_balcao, sum(x.qtd_baixa) as qtd_baixa, 
sum(x.qtd_venda) as qtd_venda
from (
select a.cod_id, a.nome, b.codigo,
sum(c.qtd_item) as qtd_itens,
0 as qtd_balcao,
0 as qtd_baixa,
0 as qtd_venda
from mv_clientes a
inner join mv_vendas_pre_itens c on(c.cod_id = a.cod_id) and (c.codigo <> 
'00')
group by a.cod_id, a.nome, b.codigo
UNION ALL
select a.cod_id, a.nome, d.codigo,
0 as qtd_itens,
sum(d.qtd_item) as qtd_balcao,
0 as qtd_baixa,
0 as qtd_venda
from mv_clientes a
inner join mv_servicos_balcao d on(d.cod_id = a.cod_id) and (d.codigo <> 
'00')
group by a.cod_id, a.nome, b.codigo
UNION ALL
select a.cod_id, a.nome, e.codigo,
0 as qtd_itens,
0 as qtd_balcao,
sum(e.qtd_item) as qtd_baixa,
0 as qtd_venda
from mv_clientes a
inner join mv_servicos_baixa e on(e.cod_id = a.cod_id) and (e.codigo <> 
'00')
group by a.cod_id, a.nome, e.codigo
UNION ALL
select a.cod_id, a.nome, f.codigo
0 as qtd_itens,
0 as qtd_balcao,
0 as qtd_baixa,
sum(f.qtd_item) as qtd_venda
from mv_clientes a
inner join mv_vendas_itens f on(f.cod_id = a.cod_id) and (f.codigo <> '00')
group by a.cod_id, a.nome, f.codigo ) as x
inner join mv_produtos b on (x.codigo = b.codigo)
group by x.cod_id, x.nome, x.codigo, b.descricao
order by 1,2,3,4

Analise o plano de execução para ver se o INNER com os produtos não ficaria 
melhor dentro do subselect. Isso teoricamente pode ser vantajoso dependendo 
da quatidade de produtos diferentes do seu cadastro e da quantidade de 
clientes diferentes do seu cadastro. Daria também para testar fazer o join 
com a mv_clientes fora da totalização inicial, como eu fiz com os produtos. 
Só testando para ver se fica só melhor ou se fica inacreditavelmente rápido.
Índices com produto, cliente e o qtd_item nas 4 tabelas totalizadas também 
poderia ajudar bastante, experimente criá-los para tentar melhorar o 
desempenho ainda mais. Novamente será a proporção clientes x produtos que 
determinará se é melhor fazer "cliente, produto, qtd_item" ou "produto, 
cliente, qtd_item". Crie os dois e veja pelo plano de execução qual o 
elefantinho mais gostou.
De qualquer forma, o princípio da otimização permanece: não há mais LEFT 
JOINs (que o elefantinho sofre para resolver), não há mais COALESCEs (que 
atrapalham a vida do elefantinho) e não há mais ORs/IS NULLs (desgraça para 
qualquer servidor SQL).

Atenciosamente,

Mozart Hasse 

_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a