Analise de vendas com SQL
Neste artigo vamos ver dois exemplos de análises de vendas utilizando SQL. Vamos ter como referência uma lista de vendas feitas durante um determinado mês. Com base nestes dados vamos extrair alguns indicadores e trabalhar com dois exemplos de análises de vendas. No primeiro exemplo vamos ver como calcular a diferença diária de vendas. No segundo exemplo vamos ver como calcular subtotais por semana. Os exemplos foram testados utilizando SQL Server e MySQL.
O que você vai aprender neste artigo?
- Calculando total e média usando as funções SUM() e AVG().
- Agrupando resultados com GROUP BY e retornando informações de acordo com o maior ou menor resultado.
- Retornar informações do registro anterior utilizando a função LAG().
- Obter o número da semana com a função WEEK() ou DATEPART().
- Calcular subtotais usando WITH ROLLUP / ROLLUP().
Para ambos os exemplos, vamos trabalhar com a seguinte tabela:
MySQL
CREATE TABLE vendas_agosto (
id INT NOT NULL AUTO_INCREMENT,
data DATE,
venda DECIMAL(10,2),
PRIMARY KEY (id)
);
SQL Server
CREATE TABLE vendas_agosto (
id INT IDENTITY(1,1) PRIMARY KEY,
data DATE,
venda DECIMAL(10,2)
);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-01",4268);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-02",2725);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-02",1725);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-03",3569);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-04",2089);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-05",2558);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-06",4419);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-06",2419);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-07",3954);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-08",4258);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-09",2570);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-10",4253);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-10",2513);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-11",3795);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-12",4277);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-13",2705);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-14",2714);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-15",3679);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-15",1609);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-16",2400);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-17",4993);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-18",4740);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-19",1394);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-20",3956);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-20",1956);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-21",1867);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-22",1719);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-23",2742);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-24",4492);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-24",2494);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-25",1760);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-26",4148);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-27",2717);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-28",4346);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-29",1446);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-29",2446);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-30",3980);
INSERT INTO vendas_agosto (data, venda) VALUES ("2024-08-31",2838);
Indicadores de vendas
Com base nesta tabela, vamos extrair alguns indicadores. Vamos responder as seguintes perguntas:
1 - Qual foi o total de vendas deste mês?
Como a tabela tem apenas 1 mês, basta somar o campo venda da tabela utiilzando a função SUM().
SELECT SUM(venda) FROM vendas_agosto
2 - Qual a média de vendas deste mês.
Este também é um indicador fácil de extrair, basta utilizar a função AVG().
SELECT AVG(venda) FROM vendas_agosto
3 - Qual o dia em que houve mais vendas e qual o valor vendido?
Para este indicador vamos ter que fazer um esforço extra. Será necessário fazer um agrupamento utilizando GROUP BY e retornar a data com base na maior soma de vendas, ordenando por ordem de maior venda e retornando a ocorrência de maior valor. O agrupamento é necessário porque eu posso ter mais de 1 registro para o mesmo dia.
MySQL
SELECT data, sum(venda) FROM vendas_agosto GROUP BY data ORDER BY sum(venda) DESC limit 1
SQL Server
SELECT TOP 1 data, sum(venda) FROM vendas_agosto GROUP BY data ORDER BY sum(venda) DESC
Existe uma observação. Como limitamos a consulta para retornar apenas um resultado, podem haver casos onde eu tenha dois registros que atendam aquela condição. Como este é um exemplo simples, vamos deixar desta forma, mas no final deste artigo vai ter um link para outro texto explicando como trabalhar com rankings, eu recomendo a leitura deste texto para se aprofundar sobre o tema.
Perceba que no MySQL e no SQL Server a forma de retornar apenas 1 registro como resultado é diferente. No MySQL se usa LIMIT no final da consulta e no SQL Server se usa TOP no começo da consulta.
4 - Qual o dia em que houve menos vendas e qual o valor vendido?
A resposta é semelhante a consulta anterior, baste alterar a ordem de ordenação.
MySQL
SELECT data, sum(venda) FROM vendas_agosto GROUP BY data ORDER BY sum(venda) limit 1
SQL Server
SELECT TOP 1 data, sum(venda) FROM vendas_agosto GROUP BY data ORDER BY sum(venda)
Agora que já terminamos de obter os indicadores, vamos as outras análises.
Calcular a diferença diárias de vendas.
Para calcular se a venda do dia atual foi maior ou menor do que a data anterior, precisamos utilizar a função LAG(). A função LAG() permite acessar um valor armazenado numa linha acima da linha atual. De forma opcional, podemos especificar o número de linhas a pular. Este tipo de função utiliza a cláusula OVER() onde vamos informar a ordenação necessária para o LAG() funcionar corretamente, em nosso caso a ordenação necessária é por data.
SELECT data,
SUM(venda) AS vendas,
(SUM(venda)-LAG(SUM(venda)) OVER (ORDER BY data ASC))
AS diferenca
FROM vendas_agosto
GROUP BY data
ORDER BY data
Calcular subtotais por semana.
Para calcular subtototais por semana precisamos primeiro saber como calcular o número da semana. A forma de obter isso vai depender do tipo de banco de dados utilizado. Para obter o número da semana no MySQL utilizamos a função WEEK(). Esta função recebe um parâmetro obrigatório que é a data e um parâmetro opcional que é um número de 0 a 6 que se refere ao dia da semana inicial da semana, sendo 0 domingo e 6 sábado. Quando não informado, a semana começa no domingo.
Já no SQL Server utilizamos DATEPART(). Esta função recebe dois parâmetros, o primeiro é o tipo de retorno desejado, e o segundo é a data usada como referência. Para definir qual o dia inicial da semana se utiliza o comando SET DATEFIRST (número), sendo que o numero deve ser de 1 a 7, sendo 1 para segunda feira e 7 para domingo. O padrão é a semana começar no domingo
MySQL
SELECT data, week(data) as semana,sum(venda) as vendas FROM
vendas_agosto
GROUP BY data
ORDER BY DATA
SQL Server
SELECT data, datepart(week, data) as semana,sum(venda) as vendas FROM
vendas_agosto
GROUP BY data
ORDER BY DATA
Agora que sabemos obter o número de semana de acordo com a data podemos calcular os subtotais por semana. Para isso utilizamos a cláusula WITH ROLLUP em conjunto com a cláusula GROUP BY. Após informar os campos utilizados no agrupamento, acrescentamos WITH ROLLUP no final.
Outra forma de fazer a mesma operação no SQL Server é utilizar ROLLUP() Como parâmetros da função ROLLUP(), informamos os campos utilizados para fazer o agrupamento. Vamos usar esta função como uma extensão do nosso agrupamento.
Nossa consulta para obter os subtotais será a seguinte:
SQL Server
SELECT datepart(week, data) as semana, data, sum(venda) as vendas FROM
vendas_agosto
GROUP BY datepart(week, data),data WITH ROLLUP
SQL Server (outra forma)
SELECT datepart(week, data) as semana, data, sum(venda) as vendas FROM
vendas_agosto
GROUP BY ROLLUP(datepart(week, data),data)
MySQL
SELECT week(data) as semana, data, sum(venda) as vendas FROM
vendas_agosto
GROUP BY week(data), data WITH ROLLUP
ENCERRAMENTO
Neste artigo você viu como calcular a diferença diária de vendas e como criar subtotais utilizando SQL
Se você gostou deste artigo os artigos a seguir podem ser de seu interesse:
Criando totais e subtotais com agrupamento no SQL