ActiveDelphi - Índice do Fórum ActiveDelphi
.: O site do programador Delphi! :.
 
 FAQFAQ   PesquisarPesquisar   MembrosMembros   GruposGrupos   RegistrarRegistrar 
 PerfilPerfil   Entrar e ver Mensagens ParticularesEntrar e ver Mensagens Particulares   EntrarEntrar 

[Resolvido] Ajuda - Erro SQL geração de estoque

 
Novo Tópico   Responder Mensagem    ActiveDelphi - Índice do Fórum -> Banco de Dados
Exibir mensagem anterior :: Exibir próxima mensagem  
Autor Mensagem
Aggelos
Novato
Novato


Registrado: Sexta-Feira, 18 de Abril de 2008
Mensagens: 69

MensagemEnviada: Qua Nov 22, 2017 8:43 am    Assunto: [Resolvido] Ajuda - Erro SQL geração de estoque Responder com Citação

Salve, amigos.

Tenho as duas tabelas abaixo:

Tabela Entrada_produto
SEQUENCIA
ID_GRUPO_PRODUTO
ID_SUB_GRUPO_PRODUTO
CODIGO_PRODUTO
DATA_FABRICACAO
QUANTIDADE
ID_UNIDADE_PRODUTO
LOTE
ENVASE
DATA_VALIDADE
DATA_ENTRADA
ID_EMPRESA
OBSERVACAO

Tabela Saida_produto
SEQUENCIA
ID_GRUPO_PRODUTO
ID_SUB_GRUPO_PRODUTO
CODIGO_PRODUTO
DATA_FABRICACAO
QUANTIDADE
ID_UNIDADE_PRODUTO
LOTE
ENVASE
DATA_VALIDADE
DATA_SAIDA
ID_EMPRESA
OBSERVACAO

Estou tentando gerar um Estoque com elas. Fiz a SQL abaixo para resgatar as informações que preciso mas está dando erro. Eu preciso que as informações não saiam repetidas pois a SQl também servirá para o futuro relatório.

SQL:

select distinct
ep1.id_grupo_produto,
grupos_produtos.nome_grupo,
ep1.id_sub_grupo_produto,
sub_grupos_produtos.nome_sub_grupo,
ep1.codigo_produto,
produtos.nome,
ep1.data_fabricacao,
(select (sum(ep2.quantidade) - sum(saida_produto.quantidade))
from entrada_produto as ep2
left join saida_produto on
((ep.codigo_produto = saida_produto.codigo_produto) and (ep2.lote = saida_produto.lote))
where ((ep2.codigo_produto = ep1.codigo_produto) and
(ep2.entrada_produto.lote = ep1.lote))) as saldo,
ep1.id_unidade_produto,
unidades_produtos.unidade,
ep1.lote,
ep1.envase,
ep1.data_validade,
ep1.data_entrada,
ep1.id_empresa,
empresas.nome_fantasia,
ep1.observacao
from
entrada_produto as ep1
left join grupos_produtos on
ep1.id_grupo_produto = grupos_produtos.id_grupo
left join sub_grupos_produtos on
ep1.id_sub_grupo_produto = sub_grupos_produtos.id_sub_grupo
left join produtos on
ep1.codigo_produto = produtos.codigo
left join unidades_produtos on
ep1.id_unidade_produto = unidades_produtos.id
left join empresas on
ep1.id_empresa = empresas.id_empresa

Estou utilizando o Firebird 2.0

Se alguém puder dar uma força, agradeço.

Abraços.


Editado pela última vez por Aggelos em Qui Nov 23, 2017 1:28 pm, num total de 1 vez
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
imex
Moderador
Moderador


Registrado: Sexta-Feira, 7 de Janeiro de 2011
Mensagens: 11666

MensagemEnviada: Qua Nov 22, 2017 9:06 am    Assunto: Responder com Citação

Bom dia,

Você pode postar um exemplo com uma pequena amostra dos registros existentes na tabela e o respectivo resultado esperado?

_________________
Assinatura: https://www.imoveisemexposicao.com.br/imoveis-alugar-guarulhos!pres_dutra-residencial-casa
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
Aggelos
Novato
Novato


Registrado: Sexta-Feira, 18 de Abril de 2008
Mensagens: 69

MensagemEnviada: Qua Nov 22, 2017 9:27 am    Assunto: Responder com Citação

imex escreveu:
Bom dia,

Você pode postar um exemplo com uma pequena amostra dos registros existentes na tabela e o respectivo resultado esperado?



Salve, imex. Vou enviar duas imagens dos dados nas tabelas e descrever mais abaixo o resultado esperado pela SQL.
Tabela entrada_produto


Tabela saida_produto


Eu preciso pegar os campos:
ep1.id_grupo_produto,
grupos_produtos.nome_grupo,
ep1.id_sub_grupo_produto,
sub_grupos_produtos.nome_sub_grupo,
codigo_produto,
produtos.nome,
data_fabricacao,
*** fazer o somatório das entradas e diminuir do somatório das saídas (campo quantidade nas duas tabelas) por produto pegando o código do produto e o lote e criar a coluna: saldo,
id_unidade_produto,
unidades_produtos.unidade,
lote,
envase,
data_validade,
data_entrada,
id_empresa,
empresas.nome_fantasia

Qualquer dúvida é só postar mensagem que eu respondo.

Obrigado desde já pela ajuda.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
imex
Moderador
Moderador


Registrado: Sexta-Feira, 7 de Janeiro de 2011
Mensagens: 11666

MensagemEnviada: Qua Nov 22, 2017 10:18 am    Assunto: Responder com Citação

Não sei se vai funcionar mas experimente fazer uns testes com a query abaixo:

Código:
select
    ep1.id_grupo_produto,
    grupos_produtos.nome_grupo,
    ep1.id_sub_grupo_produto,
    sub_grupos_produtos.nome_sub_grupo,
    ep1.codigo_produto,
    produtos.nome,
    ep1.data_fabricacao,

    sum(ep1.quantidade) -
    coalesce
        ((select sum(saida_produto.quantidade)
          from saida_produto
          where
              ep1.codigo_produto = saida_produto.codigo_produto and
              ep1.lote = saida_produto.lote), 0) as saldo,

    ep1.id_unidade_produto,
    unidades_produtos.unidade,
    ep1.lote,
    ep1.envase,
    ep1.data_validade,
    ep1.data_entrada,
    ep1.id_empresa,
    empresas.nome_fantasia,
    ep1.observacao
from entrada_produto as ep1
left join grupos_produtos on
    ep1.id_grupo_produto = grupos_produtos.id_grupo
left join sub_grupos_produtos on
    ep1.id_sub_grupo_produto = sub_grupos_produtos.id_sub_grupo
left join produtos on
    ep1.codigo_produto = produtos.codigo
left join unidades_produtos on
    ep1.id_unidade_produto = unidades_produtos.id
left join empresas on
    ep1.id_empresa = empresas.id_empresa
group by
    ep1.id_grupo_produto,
    grupos_produtos.nome_grupo,
    ep1.id_sub_grupo_produto,
    sub_grupos_produtos.nome_sub_grupo,
    ep1.codigo_produto,
    produtos.nome,
    ep1.data_fabricacao,
    ep1.id_unidade_produto,
    unidades_produtos.unidade,
    ep1.lote,
    ep1.envase,
    ep1.data_validade,
    ep1.data_entrada,
    ep1.id_empresa,
    empresas.nome_fantasia,
    ep1.observacao


Espero que ajude
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
Aggelos
Novato
Novato


Registrado: Sexta-Feira, 18 de Abril de 2008
Mensagens: 69

MensagemEnviada: Qua Nov 22, 2017 2:31 pm    Assunto: Responder com Citação

imex escreveu:
Não sei se vai funcionar mas experimente fazer uns testes com a query abaixo:

Espero que ajude


Salve, imex.

Sua SQL já ajudou bastante pois baseado nela, criei a SQL abaixo que me trás alguns valores corretos porém, outros errados... :/

SQL:

Código:
select
    ep1.id_grupo_produto,
    grupos_produtos.nome_grupo,
    ep1.id_sub_grupo_produto,
    sub_grupos_produtos.nome_sub_grupo,
    ep1.codigo_produto,
    produtos.nome,
    ep1.data_fabricacao,
    ((select sum(ep2.quantidade) from entrada_produto as ep2 where ((ep1.codigo_produto = ep2.codigo_produto) and (ep1.lote = ep2.lote) and (ep1.id_empresa = ep2.id_empresa))) -
    (select sum(saida_produto.quantidade) from saida_produto where ((ep1.codigo_produto = saida_produto.codigo_produto) and (ep1.lote = saida_produto.lote) and (ep1.id_empresa = saida_produto.id_empresa)))) as saldo,
    ep1.id_unidade_produto,
    unidades_produtos.unidade,
    ep1.lote,
    ep1.envase,
    ep1.data_validade,
    ep1.data_entrada,
    ep1.id_empresa,
    empresas.nome_fantasia
from entrada_produto as ep1
left join grupos_produtos on
    ep1.id_grupo_produto = grupos_produtos.id_grupo
left join sub_grupos_produtos on
    ep1.id_sub_grupo_produto = sub_grupos_produtos.id_sub_grupo
left join produtos on
    ep1.codigo_produto = produtos.codigo
left join unidades_produtos on
    ep1.id_unidade_produto = unidades_produtos.id
left join empresas on
    ep1.id_empresa = empresas.id_empresa


A SQL acima me retorna a seguinte listagem como na imagem abaixo:


Mas o saldo real, isto é, a soma de todas as entradas menos a soma de todas as saídas é a imagem abaixo:


O resultado da SQL teria que trazer uma listagem como na imagem acima...
Se você puder me dar uma luz de onde estou errando, agradeço imensamente.

Eu removi a função coalesce pois sempre haverá algum valor em "saldo".

Removi o group by para ver se funcionava e funcionou sem ele, então deixei sem para a SQL ficar menor um pouco.

Abraço.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
imex
Moderador
Moderador


Registrado: Sexta-Feira, 7 de Janeiro de 2011
Mensagens: 11666

MensagemEnviada: Qua Nov 22, 2017 6:52 pm    Assunto: Responder com Citação

Você pode postar como ficou o resultado da query que sugeri? O que deu errado ou faltou?

Você retirou o Group By mas em compensação adicionou o trecho abaixo, onde é feita nova leitura dos registros da tabela entrada_produto, tornando a query mais "pesada". Não sei se é necessário deixar dessa forma.
Código:
    ((select sum(ep2.quantidade) from entrada_produto as ep2 where ((ep1.codigo_produto = ep2.codigo_produto) and (ep1.lote = ep2.lote) and (ep1.id_empresa = ep2.id_empresa))) -


Sobre o Coalesce, utilizei o mesmo para evitar que o saldo fique null como está na imagem que você postou quando o item não tiver saída.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
Aggelos
Novato
Novato


Registrado: Sexta-Feira, 18 de Abril de 2008
Mensagens: 69

MensagemEnviada: Qui Nov 23, 2017 8:49 am    Assunto: Responder com Citação

imex escreveu:
Você pode postar como ficou o resultado da query que sugeri? O que deu errado ou faltou?

Você retirou o Group By mas em compensação adicionou o trecho abaixo, onde é feita nova leitura dos registros da tabela entrada_produto, tornando a query mais "pesada". Não sei se é necessário deixar dessa forma.
Código:
    ((select sum(ep2.quantidade) from entrada_produto as ep2 where ((ep1.codigo_produto = ep2.codigo_produto) and (ep1.lote = ep2.lote) and (ep1.id_empresa = ep2.id_empresa))) -


Sobre o Coalesce, utilizei o mesmo para evitar que o saldo fique null como está na imagem que você postou quando o item não tiver saída.


Bom dia, imex.

Abaixo vai a imagem com o resultado da sua query inicial:


Veja que ela trás um resultado zerado e um negativo, mas como postei na imagem abaixo, o "saldo" está positivo para todos os itens.


Eu criei a rotina do sub-select pois pensei ser necessário para fazer o somatório das quantidades dos produtos respeitando a empresa e o lote. Da forma que você fez, pensei que somaria tudo, sem haver a separação por empresa e lote.

Para falar a verdade já estou pensando em mudar essa estrutura, só não consegui pensar em uma outra que eu consiga esse saldo de maneira mais fácil e utilizando esses campos pois eles não podem sair...

Mais uma vez obrigado pela grande ajuda.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
imex
Moderador
Moderador


Registrado: Sexta-Feira, 7 de Janeiro de 2011
Mensagens: 11666

MensagemEnviada: Qui Nov 23, 2017 9:21 am    Assunto: Responder com Citação

Bom dia,

Como você obteve esse resultado da segunda imagem?
O saldo apresentado nesse resultado está separado por empresa, produto e lote?
Não sei se é coincidência mas repare que o saldo do produto 2 da empresa 1 é 1400, e na query que sugeri aparecem 2 linhas para esse produto, uma de 800 e outra de 600, cuja soma é 1400.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
Aggelos
Novato
Novato


Registrado: Sexta-Feira, 18 de Abril de 2008
Mensagens: 69

MensagemEnviada: Qui Nov 23, 2017 9:43 am    Assunto: Responder com Citação

imex escreveu:
Bom dia,

Como você obteve esse resultado da segunda imagem?
O saldo apresentado nesse resultado está separado por empresa, produto e lote?
Não sei se é coincidência mas repare que o saldo do produto 2 da empresa 1 é 1400, e na query que sugeri aparecem 2 linhas para esse produto, uma de 800 e outra de 600, cuja soma é 1400.


Eu obtive esse resultado na segunda imagem somando as entradas dos produtos e diminuindo da soma das saídas, mas sem filtro algum (de lote e empresa). Assim fica fácil pois o que está dando problema é na hora de incluir o lote e empresa na query. Porém, como os produtos são feitos por lotes, eu preciso saber qual produto está sendo vendido/transferido e quais estão disponíveis no estoque filtrando pelo lote... :/

O 800 + 600 é coincidência pois nessas imagens abaixo (que estão lá no topo do post) eu mostro todas as entradas e saídas que existem (que fiz para teste) e não tem nenhuma entrada ou saída de 600.

O que percebi é que para os produtos com somente uma entrada e uma saída, a query funciona, mas para os produtos com mais de uma entrada e mais de uma saída, gera resultado errado.

Tabela com as entradas:


Tabela com as saídas:
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
imex
Moderador
Moderador


Registrado: Sexta-Feira, 7 de Janeiro de 2011
Mensagens: 11666

MensagemEnviada: Qui Nov 23, 2017 10:14 am    Assunto: Responder com Citação

Experimente fazer uns testes removendo o campo ep1.data_entrada da query (após o Select e o Group By).
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
Aggelos
Novato
Novato


Registrado: Sexta-Feira, 18 de Abril de 2008
Mensagens: 69

MensagemEnviada: Qui Nov 23, 2017 1:39 pm    Assunto: Responder com Citação

imex escreveu:
Experimente fazer uns testes removendo o campo ep1.data_entrada da query (após o Select e o Group By).


Boa tarde, imex.

Consegui resolver.

Como dizia um professor de faculdade: "O bom é inimigo do ótimo. Se você não consegue fazer o ótimo, faço o bom."

Ao invés de gerar um estoque para as entradas e saídas, juntos, eu criei uma visão que será o estoque para as entradas e uma visão que será o estoque para as saídas. As duas visões têm os mesmos campos, assim eu pude fazer uma SQL para selecionar as entradas mas subtraindo o "saldo" das saídas. Abaixo vão os códigos criados, de repente pode ajudar mais algum membro aqui do Fórum. Smile

Visão criada para o estoque das entradas:
Código:
create view vw_estoque_entrada_produto (
  id_grupo_produto,
  nome_grupo,
  id_sub_grupo_produto,
  nome_sub_grupo,
  codigo_produto,
  nome,
  id_unidade_produto,
  unidade,
  data_fabricacao,
  lote,
  envase,
  data_validade,
  data_entrada,
  saldo,
  id_empresa,
  nome_fantasia)
as
select
  entrada_produto.id_grupo_produto,
  grupos_produtos.nome_grupo,
  entrada_produto.id_sub_grupo_produto,
  sub_grupos_produtos.nome_sub_grupo,
  entrada_produto.codigo_produto,
  produtos.nome,
  entrada_produto.id_unidade_produto,
  unidades_produtos.unidade,
  entrada_produto.data_fabricacao,
  entrada_produto.lote,
  entrada_produto.envase,
  entrada_produto.data_validade,
  entrada_produto.data_entrada,
  sum (entrada_produto.quantidade) as saldo,
  entrada_produto.id_empresa,
  empresas.nome_fantasia
from
  entrada_produto
left join grupos_produtos on
    entrada_produto.id_grupo_produto = grupos_produtos.id_grupo
left join sub_grupos_produtos on
    entrada_produto.id_sub_grupo_produto = sub_grupos_produtos.id_sub_grupo
left join produtos on
    entrada_produto.codigo_produto = produtos.codigo
left join unidades_produtos on
    entrada_produto.id_unidade_produto = unidades_produtos.id
left join empresas on
    entrada_produto.id_empresa = empresas.id_empresa
group by
    entrada_produto.id_grupo_produto,
    grupos_produtos.nome_grupo,
    entrada_produto.id_sub_grupo_produto,
    sub_grupos_produtos.nome_sub_grupo,
    entrada_produto.codigo_produto,
    produtos.nome,
    entrada_produto.data_fabricacao,
    entrada_produto.id_unidade_produto,
    unidades_produtos.unidade,
    entrada_produto.lote,
    entrada_produto.envase,
    entrada_produto.data_validade,
    entrada_produto.data_entrada,
    entrada_produto.id_empresa,
    empresas.nome_fantasia


Visão criada para o estoque das saídas:
Código:
create view vw_estoque_saida_produto (
  ID_GRUPO_PRODUTO,
  NOME_GRUPO,
  ID_SUB_GRUPO_PRODUTO,
  NOME_SUB_GRUPO,
  CODIGO_PRODUTO,
  NOME,
  ID_UNIDADE_PRODUTO,
  UNIDADE,
  DATA_FABRICACAO,
  LOTE,
  ENVASE,
  DATA_VALIDADE,
  DATA_saida,
  SALDO,
  ID_EMPRESA,
  NOME_FANTASIA)
as
select
  saida_produto.id_grupo_produto,
  grupos_produtos.nome_grupo,
  saida_produto.id_sub_grupo_produto,
  sub_grupos_produtos.nome_sub_grupo,
  saida_produto.codigo_produto,
  produtos.nome,
  saida_produto.id_unidade_produto,
  unidades_produtos.unidade,
  saida_produto.data_fabricacao,
  saida_produto.lote,
  saida_produto.envase,
  saida_produto.data_validade,
  saida_produto.data_saida,
  sum (saida_produto.quantidade) as saldo,
  saida_produto.id_empresa,
  empresas.nome_fantasia
from
  saida_produto
left join grupos_produtos on
    saida_produto.id_grupo_produto = grupos_produtos.id_grupo
left join sub_grupos_produtos on
    saida_produto.id_sub_grupo_produto = sub_grupos_produtos.id_sub_grupo
left join produtos on
    saida_produto.codigo_produto = produtos.codigo
left join unidades_produtos on
    saida_produto.id_unidade_produto = unidades_produtos.id
left join empresas on
    saida_produto.id_empresa = empresas.id_empresa
group by
    saida_produto.id_grupo_produto,
    grupos_produtos.nome_grupo,
    saida_produto.id_sub_grupo_produto,
    sub_grupos_produtos.nome_sub_grupo,
    saida_produto.codigo_produto,
    produtos.nome,
    saida_produto.data_fabricacao,
    saida_produto.id_unidade_produto,
    unidades_produtos.unidade,
    saida_produto.lote,
    saida_produto.envase,
    saida_produto.data_validade,
    saida_produto.data_saida,
    saida_produto.id_empresa,
    empresas.nome_fantasia


SQL criada para gerar o estoque:
Código:
select
  vw_estoque_entrada_produto.id_grupo_produto,
  vw_estoque_entrada_produto.nome_grupo,
  vw_estoque_entrada_produto.id_sub_grupo_produto,
  vw_estoque_entrada_produto.nome_sub_grupo,
  vw_estoque_entrada_produto.codigo_produto,
  vw_estoque_entrada_produto.nome,
  vw_estoque_entrada_produto.id_unidade_produto,
  vw_estoque_entrada_produto.unidade,
  vw_estoque_entrada_produto.data_fabricacao,
  vw_estoque_entrada_produto.lote,
  vw_estoque_entrada_produto.envase,
  vw_estoque_entrada_produto.data_validade,
  vw_estoque_entrada_produto.data_entrada,
  coalesce((vw_estoque_entrada_produto.saldo - vw_estoque_saida_produto.saldo), vw_estoque_entrada_produto.saldo) as saldo,
  vw_estoque_entrada_produto.id_empresa,
  vw_estoque_entrada_produto.nome_fantasia
from
  vw_estoque_entrada_produto
left join vw_estoque_saida_produto on
    vw_estoque_entrada_produto.codigo_produto = vw_estoque_saida_produto.codigo_produto and
    vw_estoque_entrada_produto.lote = vw_estoque_saida_produto.lote and
    vw_estoque_entrada_produto.id_empresa = vw_estoque_saida_produto.id_empresa


Agora é alterar as rotinas no Delphi... Sad Smile

Obrigado mais uma vez pela ajuda, amigo. Se passar por Friburgo/RJ, avise para trocarmos uma ideia. Smile

Abraços.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
Mostrar os tópicos anteriores:   
Novo Tópico   Responder Mensagem    ActiveDelphi - Índice do Fórum -> Banco de Dados Todos os horários são GMT - 3 Horas
Página 1 de 1

 
Ir para:  
Enviar Mensagens Novas: Proibido.
Responder Tópicos Proibido
Editar Mensagens: Proibido.
Excluir Mensagens: Proibido.
Votar em Enquetes: Proibido.


Powered by phpBB © 2001, 2005 phpBB Group
Traduzido por: Suporte phpBB