Curva ABC do produto em java [RESOLVIDO]

Olá pessoal,
Procurei na internet algum tópico referente ao consumo de venda de um produto mês a mês e não achei nada referente ao assunto.
Talvez vocês possam dar uma luz como fazer está regra…

Tenho um sistema onde os produtos de venda, baixa a quantidade em estoque e atualiza um campo a quantidade vendida (acumulativo), independente do dia ou mês da suposta venda, também tenho campo da data da venda.

Preciso que um período de doze meses seja registrado em cada mês a quantidade de venda do produto, sendo isto automático, terminando o mês passa a registrar a quantidade vendida no mês vigente.
Ex.: Produto = X SET = 10 OUT = 12 NOV = 7 DEZ = 4

Oi Márcio,

Deixa eu ver se entendi. Vc quer guardar a quantidade de produtos que foram vendidos em um mês? É isso?

Vc tem a data da venda e a quantidade que foi vendida naquela data? Se tiver esses dados, vc não precisa ficar armazenando, basta fazer uma consulta no seu banco de dados para retornar os dados que você quer. Se tem como calcular dinamicamente, a necessidade de armazenar some entendeu? É até preferível na maioria dos casos.

Oi David,
Obrigado pelo seu retorno.
Vou tentar explicar o que eu preciso…
No produto ou melhor na tabela do produto tempo um campo chamado ‘qtde_venda’, mas este campo é alimentado com as vendas efetuadas independente do mês da venda.
Preciso que está quantidade vendida seja guardada mês a mês na tabela produto ou em outra tabela.
Para que possa estar gerando informações para uma sugestão de compra com a média de vendas dos meses entre um período de doze meses.
Com estas quantidades vendidas de cada mês e vinculada ao produto, conseguirei gerar uma real Curva ABC do produto que conterá a frequência de venda, quantidade de venda e valor de venda.
Abaixo as tabelas de produtos, vendas e vendas de produto está vinculada a tabela de vendas.

– Estrutura da tabela produtos

CREATE TABLE produtos (
codigo int(11) NOT NULL,
nome varchar(255) DEFAULT NULL,
descricao varchar(255) NOT NULL,
valor double NOT NULL,
valor_custo double DEFAULT 0,
codigo_barras_ean varchar(14) DEFAULT ‘0’,
estoque float DEFAULT NULL,
qtde_min int(11) DEFAULT NULL,
qtde_venda float DEFAULT NULL,
imagem_produto varchar(255) DEFAULT NULL,
ativo int(11) NOT NULL DEFAULT 1,
dias_garantia int(11) DEFAULT NULL,
origem int(11) DEFAULT NULL,
peso double DEFAULT NULL,
ncm varchar(8) DEFAULT NULL,
tipo_ncm varchar(5) DEFAULT NULL,
trib_st_perc double DEFAULT NULL,
icms_cst double DEFAULT NULL,
icms double DEFAULT NULL,
icms_red double DEFAULT NULL,
ipi_cst varchar(2) DEFAULT NULL,
ipi double DEFAULT NULL,
pis_cst varchar(2) DEFAULT NULL,
pis double DEFAULT NULL,
cofins_cst varchar(2) DEFAULT NULL,
cofins double DEFAULT NULL,
unidade_medida bigint(20) UNSIGNED NOT NULL,
locacao varchar(10) NOT NULL,
categoria_cod int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

– Estrutura da tabela vendas

CREATE TABLE vendas (
codigo int(11) NOT NULL,
clientes_codigo int(11) NOT NULL,
placas_codigo int(11) NOT NULL,
data_venda date DEFAULT NULL,
valor_total float DEFAULT NULL,
desconto float DEFAULT NULL,
tipo tinyint(1) NOT NULL,
observacao varchar(2000) CHARACTER SET utf8 DEFAULT ’ ',
tipo_pagamento int(10) UNSIGNED NOT NULL,
codigo_usuario int(10) UNSIGNED NOT NULL,
taxa_entrega float NOT NULL DEFAULT 0,
acrescimo_porc float NOT NULL,
acrescimo_valor float NOT NULL,
troco float NOT NULL,
tipo_venda tinyint(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

– Estrutura da tabela vendas_produto

CREATE TABLE vendas_produto (
codigo int(11) NOT NULL,
quantidade float DEFAULT NULL,
valor_unitario double NOT NULL,
codigo_venda int(11) NOT NULL,
codigo_produto int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Oi Márcio, então, vc pode fazer como eu falei. Vc não precisa armazenar esse dado, pq vc já o tem! É só agrupar por mês e ano e somar as quantidades. Se eu não errei nada, nem no SQL, nem no nome das suas tabelas e colunas, seria algo como:

SELECT 
    p.nome nome,
    SUM(vp.quantidade) totalVendas,
    MONTH(v.data_venda) mes,
    YEAR(v.data_venda) ano
FROM
    produtos p,
    vendas v,
    vendas_produto vp
WHERE
    p.codigo = vp.codigo_produto AND
    v.codigo = vp.codigo_venda
GROUP BY 
    MONTH(v.data_venda) AND
    YEAR(v.data_venda);

Obrigado David pelo retorno,
Sua sugestão funcionou, mas fico preocupado quando efetuar está consulta com centenas de produtos selecionados, pode demorar a demonstrar o resultado.

Estou me aperfeiçoando no java, assim tenho algumas limitações ainda.
O seu select está agrupando tudo em um único produto, ou melhor, o ultimo das vendas.

nome totalVedas mes ano
cabeçote 3 12 2020

mas preciso que seja assim:

nome totalVedas mes ano
cabeçote 2 12 2020
parafuso 1 12 2020

segue o dados do banco:

CREATE TABLE vendas (
codigo int(11) NOT NULL,
clientes_codigo int(11) NOT NULL,
placas_codigo int(11) NOT NULL,
data_venda date DEFAULT NULL,
valor_total float DEFAULT NULL,
desconto float DEFAULT NULL,
tipo tinyint(1) NOT NULL,
observacao varchar(2000) CHARACTER SET utf8 DEFAULT ’ ',
tipo_pagamento int(10) UNSIGNED NOT NULL,
codigo_usuario int(10) UNSIGNED NOT NULL,
taxa_entrega float NOT NULL DEFAULT 0,
acrescimo_porc float NOT NULL,
acrescimo_valor float NOT NULL,
troco float NOT NULL,
tipo_venda tinyint(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


– Extraindo dados da tabela vendas

INSERT INTO vendas (codigo, clientes_codigo, placas_codigo, data_venda, valor_total, desconto, tipo, observacao, tipo_pagamento, codigo_usuario, taxa_entrega, acrescimo_porc, acrescimo_valor, troco, tipo_venda) VALUES
(2, 1, 0, ‘2020-12-19’, 679.99, 0, 1, ‘’, 0, 1, 0, 0, 0, 0, 0),
(3, 1, 0, ‘2020-12-20’, 197.46, 0, 1, ‘’, 0, 1, 0, 0, 0, 0, 0);

CREATE TABLE vendas_produto (
codigo int(11) NOT NULL,
quantidade float DEFAULT NULL,
valor_unitario double NOT NULL,
codigo_venda int(11) NOT NULL,
codigo_produto int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


– Extraindo dados da tabela vendas_produto

INSERT INTO vendas_produto (codigo, quantidade, valor_unitario, codigo_venda, codigo_produto) VALUES
(2, 1, 679.99, 2, 9),
(3, 2, 98.73, 3, 8);

Você não deve se preocupar em absoluto com o banco. Se fosse algo na ordem de centenas de milhões de registros, até vá lá, mas não acho que seja esse o seu cenário. Tudo que você puder delegar para o SGBD fazer, faça! Te garanto que uma solução local no seu programa, ou paliativa como armazenamento de um atributo que pode ser calculado pelo próprio SGBD, sempre será mais lento do que deixar o SGBD cuidar do problema. Ele tem cache, tem índices, etc. Quanto à query, faltou agrupar o nome do produto. Da forma que estava, o agrupamento estava sendo feito por mês e ano, agora ele agrupa também o nome. Deve funcionar.

SELECT 
    p.nome nome,
    SUM(vp.quantidade) totalVendas,
    MONTH(v.data_venda) mes,
    YEAR(v.data_venda) ano
FROM
    produtos p,
    vendas v,
    vendas_produto vp
WHERE
    p.codigo = vp.codigo_produto AND
    v.codigo = vp.codigo_venda
GROUP BY 
    p.nome AND
    MONTH(v.data_venda) AND
    YEAR(v.data_venda);

Vou seguir este caminho no meu programa.
Referente a query, tive de tirar o agrupamento por mês e ano, deu certo que eu queria.
Muito obrigado pelas informações e ajuda na montagem da query.
Um Feliz Natal para você e sua família!

Disponha Márcio!
Feliz natal para você e sua família tbm!