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