Caso ainda não conheça a função "SUM", veja o artigo "Mysql SUM - Soma "
Caso tenha interesse, faça o download ou veja o script deste artigo no github.
O script também está disponível para execução no Sql Fiddle e foi testado no Mysql 5.1.61.
1º Exemplo
Vamos calcular as despesas com fornecedor para cada segmento de uma empresa.
Iremos exibir o subtotal por segmento: "Papelaria e informática", "Marcenaria", "Serralheria" e "Limpeza e higiêne".
Também vamos exibir no final da consulta o total geral para todos os segmentos.
Neste exemplo, utilizaremos a tabela "tb_fornecedor". Veja a imagem da tabela a seguir:
Solução
Vamos utilizar a função "SUM" acompanhada de "GROUP BY" para fazer a quebra por segmento. Além disso vamos utilizar o "WITH ROLLUP" para exibir o subtotal embaixo de cada quebra e o total geral no último registro.
Veja a sentença abaixo:
SELECT
segmento,
produto,
SUM(valor)
FROM tb_fornecedor
GROUP BY segmento, produto WITH ROLLUP;
Após a execução da sentença teremos o resultado exibido a seguir:
2º Exemplo
Para facilitarmos a interpretação do resultado da consulta vamos alterar o conteúdo da primeira coluna:
- Nos registros que exibirem o subtotal, a primeira coluna será acompanhada da palavra "Subtotal" e do nome do segmento;
- O ultimo registro da primeira coluna se chamará "Total Geral";
- Nos outros registros o nome do segmento será mantido;
Veja a sentença abaixo:
SELECT
IF
(
segmento IS NULL,
'Total Geral',
IF (produto IS NULL, CONCAT('Subtotal - ', segmento), segmento)
)
AS segmento,
produto,
SUM(valor) as valor
FROM tb_fornecedor
GROUP BY segmento, produto WITH ROLLUP;
- Utilizamos a condição "IF" para verificar onde o segmento era nulo e substituímos por "Total Geral";
- Para segmento não nulo fizemos uma outra verificação. Foi encadeado um outro "IF" para verificar onde o produto era nulo e substituímos por "Subtotal" acompanhado do nome do segmento, caso o produto não fosse nulo mantivemos o nome do segmento;
- Observação: utilizamos a função "CONCAT" para unir a palavra "Subtotal" ao conteúdo da coluna segmento;
3º Exemplo
Não é possível utilizar "WITH ROLLUP" com "ORDER BY" na mesma consulta. Neste exemplo, vamos mostrar como ordenar colunas utilizando uma subquery (subconsulta). Vamos ordenar as colunas "segmento" e "produto" em ordem decrescente.
Solução
Veja a sentença abaixo:
SELECT
COALESCE(segmento, 'TOTAL GERAL') AS segmento,
CASE
WHEN ((segmento IS NOT NULL) AND (produto IS NULL))
THEN CONCAT('Subtotal - ', segmento)
WHEN (segmento IS NOT NULL AND produto IS NOT NULL)
THEN produto
END AS produto,
valor FROM
(
SELECT
segmento,
produto,
SUM(valor) AS valor
FROM tb_fornecedor
GROUP BY segmento, produto WITH ROLLUP
) TOTAL
ORDER BY
CASE
WHEN(segmento IS NOT NULL) THEN 0
ELSE 1
END,
segmento DESC,
CASE
WHEN(produto IS NOT NULL) THEN 0
ELSE 1
END,
produto DESC;
A subquery que criamos está destacada na cor azul e posicionada entre parenteses, esta subquery recebeu o alias (apelido) de TOTAL.
Observação: perceba que no "ORDER BY" utilizamos duas vezes o "CASE WHEN":
- o primeiro para que o "TOTAL GERAL" fosse exibido no último registo da coluna "segmento" independente da ordem alfabética;
- o segundo para que o "Subtotal" fosse exibido no final de cada segmento da coluna "produto" independente da ordem alfabética;
Deixe o seu comentário ou sugestão.
Gostou? Siga no Google + ou Facebook.
Muito bom.
ResponderExcluirMuito agradecido. Fiquei muito satisfeito com sua dica.
ResponderExcluirBom dia quando eu utilizo JOIN´s este código não funciona.
ResponderExcluirPoderia me ajudar?
o script é este
SELECT
COALESCE(usuario.user_name,'TOTAL GERAL')
CONCAT(
SUBSTR(usuario.user_name,1,3),'.',
SUBSTR(usuario.user_name,4,3),'.',
SUBSTR(usuario.user_name,7,3),'-',
SUBSTR(usuario.user_name,10)) as CPF,
usuario.user_first_name AS Nome,
usuario.user_email AS 'E-mail',
curso.group_name AS Curso,
extra.field_3 AS Perfil,
extra.field_4 AS DR,
usuario.user_company AS Empresa,
FROM users_in_groups matricula
JOIN users usuario ON (matricula.user_id = usuario.user_id and usuario.user_name IS NOT NULL)
JOIN groups curso ON (matricula.group_id = curso.group_id)
JOIN users_extended extra ON (matricula.user_id = extra.e_user_id)
GROUP BY usuario.user_first_name WITH ROLLUP
limit 500
meu e-mail slc.luciano@gmail.com
Excluir