1
resposta

[Sugestão] minha resolução

create view acima_vol_alura as
select
count(distinct nf.NUMERO) as qtd_compras,
c.cpf,
format(sum(inf.QUANTIDADE*inf.PRECO),'N2','pt-BR') as valor_mensal,
sum(inf.quantidade) as vol_mes,
c.VOLUME_DE_COMPRA,
month(nf.data_venda) as mes,
c.NOME,
case
when sum(inf.quantidade) > c.VOLUME_DE_COMPRA then 'acima'
when sum(inf.quantidade) < c.VOLUME_DE_COMPRA then 'abaixo'
else 'igual' end as sit_vol_compra_mes

from NOTAS_FISCAIS nf
inner join ITENS_NOTAS_FISCAIS inf
on inf.NUMERO = nf.NUMERO
INNER JOIN TABELA_DE_CLIENTES c on c.CPF = nf.CPF
where year(DATA_VENDA) = 2016 and month(DATA_VENDA) in(select MONTH(DATA_VENDA) FROM NOTAS_FISCAIS where year(DATA_VENDA)=2016)
group by
month(DATA_VENDA),
c.CPF,
c.VOLUME_DE_COMPRA,
c.NOME

;

select
acima_vol_alura.*,
round(((vol_mes/VOLUME_DE_COMPRA)*100 - 100),2) as percentual_acima
from acima_vol_alura
where sit_vol_compra_mes ='acima';

1 resposta

Olá, Estudante. Como vai?

Parabéns pela resolução do desafio! A sua estrutura de consulta ficou muito boa. Você conseguiu unificar as tabelas corretas utilizando o INNER JOIN, aplicou a agregação com GROUP BY de forma precisa e utilizou com maestria a estrutura condicional CASE WHEN para classificar o status do volume de compras.

Criar uma View (create view acima_vol_alura as...) para salvar essa lógica foi uma excelente decisão de arquitetura. As Views ajudam a simplificar consultas complexas no dia a dia do analista ou desenvolvedor de banco de dados, permitindo reutilizar o código sem precisar reescrever toda a lógica de junções e agrupamentos.

Para agregar ainda mais valor ao seu aprendizado, identifiquei uma oportunidade de otimização na cláusula WHERE da sua View, especificamente neste trecho:

where year(DATA_VENDA) = 2016 and month(DATA_VENDA) in(select MONTH(DATA_VENDA) FROM NOTAS_FISCAIS where year(DATA_VENDA)=2016)

Por que podemos simplificar isso?

A subconsulta interna (select MONTH(DATA_VENDA) FROM NOTAS_FISCAIS where year(DATA_VENDA)=2016) vai retornar uma lista com todos os meses que possuem vendas no ano de 2016 (provavelmente os meses de 1 a 12).

Ao dizer que o mês da nota fiscal precisa estar contido nessa lista de meses de 2016, você está fazendo uma checagem redundante. Afinal, se a venda já aconteceu no ano de 2016, o mês dela obrigatoriamente fará parte dos meses existentes daquele ano. Essa verificação extra faz com que o SQL Server gaste poder de processamento rodando uma subconsulta desnecessária para cada linha.

Podemos simplificar o WHERE deixando apenas o filtro do ano, o que tornará a execução da sua View muito mais rápida em bases de dados volumosas:

where year(DATA_VENDA) = 2016

Uma sugestão de boa prática: Evitando a divisão por zero

Na sua consulta final, você realiza o seguinte cálculo matemático:
round(((vol_mes/VOLUME_DE_COMPRA)*100 - 100),2)

Como a sua consulta final filtra apenas onde sit_vol_compra_mes = 'acima', nós sabemos que o vol_mes é maior que o VOLUME_DE_COMPRA. Porém, se por um acaso algum cliente novo for cadastrado no sistema com o VOLUME_DE_COMPRA zerado ou nulo, o SQL Server irá retornar um erro crítico de divisão por zero (Division by zero error) e travará o seu relatório.

Para blindar o seu código contra esse tipo de imprevisto na base de dados, uma boa prática no SQL Server é utilizar a função NULLIF. Ela transforma o valor em NULL caso ele seja zero, e qualquer divisão por NULL resulta em NULL com segurança, em vez de quebrar a aplicação:

select
    acima_vol_alura.*,
    round(((vol_mes / nullif(VOLUME_DE_COMPRA, 0)) * 100 - 100), 2) as percentual_acima
from acima_vol_alura
where sit_vol_compra_mes = 'acima';

Acompanhar o volume de compras é um excelente exemplo de análise de dados corporativos reais. Continue praticando e explorando o poder das consultas avançadas no SQL Server!

Espero que possa ter lhe ajudado!