verificar variação de quantidade entre 2 datas

Dúvidas, dicas e truques de SQL, Select, Update, Delete, cláusulas, operações com joins, Funções em SQLs, etc
Robson Costa
Rank: Analista Sênior
Rank: Analista Sênior
Mensagens: 155
Registrado em: Sex, 17 Out 2008 6:05 pm
Localização: Campo Grande - MS

Olá,

Tenho uma tabela com a seguinte estrutura:

CodProd
Qtd
Data

Tenho que fazer um script onde eu possa verificar a variação de quantidade de um determinado produto entre duas datas.

Porém pode ser que em uma determinada data escolhida este produto não tenha, mas eu quero que seja feito cálculo entre uma data que o produto esteja listado e um que não esteja.

Como eu faria? Eu tentei este script e não deu certo:

Selecionar tudo

   select p.nomprod,a.qtd,b.qtd,b.qtd - a.qtd
         from tab1 p,tab2 a,tab2 b
         where a.data = <data1> and
                   b.data = <data2> and
                   a.codprod = b.codprod and
                   b.codprod = p.codprod
Avatar do usuário
stcoutinho
Moderador
Moderador
Mensagens: 850
Registrado em: Qua, 11 Mai 2011 5:15 pm
Localização: são Paulo - SP

Robsoncosta,

Pelo que pude entender do seu problema, temos as seguintes premissas

- As quantidades indicam o "nivel de estoque de um produto"
- Você pode ter ou não incidencias de um produto, de acordo com o periodo inicial e final informado pelo usuario.

Uma das opções para solucionar seu problema seria usar a funcionalidade de DENSE_RANK.

O DENSE_RANK lhe permite "ranquear" (classificar) um conjunto de registros conforme um determinada ordenação.

Sendo assim:

A) Identificar - para cada produto - a "data minima" mais próxima de <data1>, e que se encontre dentro do periodo informado:

Selecionar tudo

-- Classifica as ocorrencias de um produto por ordem crescente de data
SELECT CODPROD,
       DATA,
       QTD,
       DENSE_RANK() OVER (PARTITION BY CODPROD ORDER BY DATA ASC) AS RANK
  FROM TAB2
 WHERE DATA BETWEEN <data1> AND <data2>
B) Identificar - para cada produto - a "data maxima" mais próxima de <data2>, e que se encontre dentro do periodo informado:

Selecionar tudo

-- Classifica as ocorrencias de um produto por ordem decrescente de data
SELECT CODPROD,
       DATA,
       QTD,
       DENSE_RANK() OVER (PARTITION BY CODPROD ORDER BY DATA DESC) AS RANK
  FROM TAB2
 WHERE DATA BETWEEN <data1> AND <data2>
C) Classificados os registros (notas de rank) em ordem crescente, identificar para cada produto a "primeira ocorrencia" (data minima dentro do periodo, que terá a nota "1"):

Selecionar tudo

--- Seleciona as primeiras ocorrencias de datas de cada produto
--- Estas datas são as mais proximas a data inicial <data1>
SELECT CODPROD,
       DATA AS DATA_INI,
       QTD  AS QT_INI,
  FROM (-- Classifica as ocorrencias de um produto por ordem crescente de data
        SELECT CODPROD,
               DATA,
               QTD,
               DENSE_RANK() OVER (PARTITION BY CODPROD ORDER BY DATA ASC) AS RANK
          FROM TAB2
         WHERE DATA BETWEEN <data1> AND <data2>)
 WHERE RANK = 1

D) Classificados os registros (notas de rank) em ordem decrescente, identificar para cada produto a "ultima ocorrencia" (data maxima dentro do periodo, que terá a nota "1"):

Selecionar tudo

--- Seleciona as ultimas  ocorrencias de datas de cada produto
--- Estas datas são as mais proximas a data final <data2>
SELECT CODPROD,
       DATA AS DATA_FIM,
       QTD  AS QT_FIM,
  FROM (-- Classifica as ocorrencias de um produto por ordem crescente de data
        SELECT CODPROD,
               DATA,
               QTD,
               DENSE_RANK() OVER (PARTITION BY CODPROD ORDER BY DATA DESC) AS RANK
          FROM TAB2
         WHERE DATA BETWEEN <data1> AND <data2>)
 WHERE RANK = 1
F) Finalmente juntamos tudo em uma única querie:

Selecionar tudo

SELECT P.NOMPROD,
       I.DATA_INI,
       F.DATA_FIM,
       I.QTD_INI,
       F.QTD_FIM,
       (F.QTD_FIM - F.QTD_INI) DIFERENCA
 FROM  (SELECT CODPRODP,NOMPROD FROM TAB1) P,      
       (SELECT CODPROD,
               DATA AS DATA_INI,
               QTD  AS QT_INI,
          FROM (SELECT CODPROD,
                       DATA,
                       QTD,
                       DENSE_RANK() OVER (PARTITION BY CODPROD ORDER BY DATA ASC) AS RANK
                  FROM TAB2
                 WHERE DATA BETWEEN <data1> AND <data2>)
         WHERE RANK = 1) I,         
       (SELECT CODPROD,
               DATA AS DATA_INI,
               QTD  AS QT_INI,
          FROM (SELECT CODPROD,
                       DATA,
                       QTD,
                       DENSE_RANK() OVER (PARTITION BY CODPROD ORDER BY DATA DESC) AS RANK
                  FROM TAB2
                 WHERE DATA BETWEEN <data1> AND <data2>)
         WHERE RANK = 1) F         
  WHERE P.CODPROD = I.CODPROD (+)       
    AND P.CODPROD = F.CODPROD (+)
  ORDER BY P.CODPROD

Espero que os exemplos acima lhe deêm uma idéia de como resolver este problema.

Os exemplos acima não foram testados, e provavelmente você terá que fazer um ou outro acerto. O mais importante aqui é passar o conceito do DENSE_RANK.



Abraços,

Sergio Coutinho
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 15 visitantes