填充缺失日期和最长日期

时间:2013-07-16 11:31:09

标签: sql oracle

我从银行系统获得以下数据:date, product code, due date.

我需要做的是向后填充每个产品due_dates,即前几个月,但仅限于due_date <= date.

我还想在每个产品中填充max_date,这是最近的due_date的日期。

如您所见,我可能在一个产品中有许多due_dates或没有。

如果有多个日期,则不应覆盖之前的日期。

这就是现在的样子:

    date        product    due_date
------------------------------------------
    2012-01-31    a1           
    2012-02-28    a1           
    2012-01-31    b1           
    2012-02-28    b1           
    2012-03-31    b1           
    2012-04-30    b1       2012-02-18    
    2012-05-31    b1           
    2012-06-30    b1       2012-05-31   
    2012-07-31    b1         
    2012-08-31    b1
    2012-09-30    b1       2012-09-01
    2012-10-31    b1
    2012-04-30    c1         
    2012-05-31    c1         
    2012-06-30    c1       2011-03-01    
    2012-07-31    c1      

这是我想得到的结果:

     date        product    due_date      max_date
--------------------------------------------------------
     2012-01-31    a1           
     2012-02-28    a1           
     2012-01-31    b1                     2012-09-30
     2012-02-28    b1       2012-02-18    2012-09-30
     2012-03-31    b1       2012-02-18    2012-09-30
     2012-04-30    b1       2012-02-18    2012-09-30
     2012-05-31    b1       2012-05-31    2012-09-30
     2012-06-30    b1       2012-05-31    2012-09-30
     2012-07-31    b1                     2012-09-30
     2012-08-31    b1                     2012-09-30
     2012-09-30    b1       2012-09-01    2012-09-30
     2012-10-31    b1                     2012-09-30
     2012-04-30    c1       2011-03-01    2012-06-30
     2012-05-31    c1       2011-03-01    2012-06-30
     2012-06-30    c1       2011-03-01    2012-06-30
     2012-07-31    c1                     2012-06-30

2 个答案:

答案 0 :(得分:1)

请参阅SQL Fiddle

SELECT
   t1.date_
 , t1.product
  , case 
    when t1.due_date is not null then t1.due_date
    else ( 
          select max(due_date) 
          from sot t2 
          where t2.product = t1.product 
            and t2.due_date <= t1.date_
            and t2.date_ > t1.date_
          )
    end                                   
                  as due_date
, t3.max_date
FROM 
    sot t1
    left outer join (  select product, max(date_) keep (dense_rank first order by due_date desc)  as max_date 
                       from sot  
                      where due_date is not null 
                      group by product
                    ) t3
    on (t3.product = t1.product)
order by product, date_;

due_date的计算表现不佳,但我目前没有看到更好的替代方案

答案 1 :(得分:1)

尝试使用此查询可能会有用,适用于您的数据示例,(您可以尝试 here ):

WITH temp1 AS (
  SELECT ROW_NUMBER() OVER (PARTITION BY product ORDER BY date_f,product ASC) AS row_num,
             date_f,
             product,
             due_date
   FROM TEST
), temp2 AS (
  SELECT row_num,date_f,product, due_date FROM temp1 WHERE NOT due_date IS NULL
), temp3 AS (
  SELECT product, MAX(date_f) AS max_due_date
  FROM TEST
  WHERE NOT due_date IS NULL
  GROUP BY product
)
SELECT 
to_char(a.date_f,'YYYY-MM-DD') AS DATE_F, 
a.product,
to_char(NVL(a.due_date,
  (SELECT MIN(b.due_date) 
   FROM temp2 b 
   WHERE b.product = a.product AND b.due_date <= a.date_f AND a.row_num < b.row_num)),'YYYY-MM-DD') AS due_date,
to_char(
  (SELECT c.max_due_date FROM temp3 c
  WHERE c.product = a.product AND ROWNUM = 1),'YYYY-MM-DD') AS max_date
FROM temp1 a

注意:目前我无法做得更好:(