1

I have following data from banking system: date, product code, due date.

What I need to do is to populate for each product due_dates backwards i.e. for previous months but only on condition that due_date <= date.

I would also like to populate max_date that is date for the most recent due_date within each product.

As you can see, I may have many due_dates within one product or none.

If there is more than one date, previous shouldn't be overwritten.

This is what it looks like now:

    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      

and this is the result I would like to get:

     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
4

2 回答 2

1

SQL 小提琴

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 的计算性能不佳,但目前我没有看到任何更好的选择

于 2013-07-16T14:13:15.673 回答
1

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

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

注意:我现在不能做得更好:(

于 2013-07-16T14:51:00.107 回答