2016-05-12 55 views
3

我有一个收入和开始/结束日期如下ID的数据库,但我无法打破给定的开始/结束日期范围每月每ID的收入。如何编写查询以显示两个日期之间的月份?

表数据的样品低于:

ID | INCOME | START_DATE | END_DATE 
1 | 2000 | 02/01/2016 | 05/31/2016 
1 | 1500 | 12/01/2015 | 01/31/2016 
2 | 1000 | 01/01/2016 | 04/30/2016 

结果应该是:

ID | INCOME | MONTH 
1 | 2000 | 05/2016 
1 | 2000 | 04/2016 
1 | 2000 | 03/2016 
1 | 2000 | 02/2016 
1 | 1500 | 01/2016 
1 | 1500 | 12/2015 
2 | 1000 | 04/2016 
2 | 1000 | 03/2016 
2 | 1000 | 02/2016 
2 | 1000 | 01/2016 

我怎么会写甲骨文的SQL,使得我能够有效地产生上述结果(假设该表有成千上万的唯一ID)?

+0

什么版本的Oracle数据库? – mathguy

+0

版本3.2.20.09 –

+0

?目前的Oracle版本是12,你当然不在Oracle 3上?要找出你的版本,运行'select * from v $ version;' – mathguy

回答

2

为此,您可以使用连接通过,像这样:

with sample_data as (select 1 id, 2000 income, to_date('01/02/2016', 'dd/mm/yyyy') start_date, to_date('31/05/2016', 'dd/mm/yyyy') end_date from dual union all 
        select 1 id, 1500 income, to_date('01/12/2015', 'dd/mm/yyyy') start_date, to_date('31/01/2016', 'dd/mm/yyyy') end_date from dual union all 
        select 2 id, 1000 income, to_date('01/01/2016', 'dd/mm/yyyy') start_date, to_date('30/04/2016', 'dd/mm/yyyy') end_date from dual) 
select id, 
     income, 
     add_months(trunc(start_date, 'mm'), -1 + level) mnth 
from sample_data 
connect by prior id = id 
      and prior income = income 
      and prior sys_guid() is not null 
      and add_months(trunc(start_date, 'mm'), -1 + level) <= trunc(end_date, 'mm') 
order by id, income desc, mnth desc; 


     ID  INCOME MNTH  
---------- ---------- --------- 
     1  2000 01-MAY-16 
     1  2000 01-APR-16 
     1  2000 01-MAR-16 
     1  2000 01-FEB-16 
     1  1500 01-JAN-16 
     1  1500 01-DEC-15 
     2  1000 01-APR-16 
     2  1000 01-MAR-16 
     2  1000 01-FEB-16 
     2  1000 01-JAN-16 
+0

谢谢骨科医生!他们都相应地工作! –

2

你可以使用recursive subquery factoring,如果你是在11gR2中或更高:

with r (id, income, this_date, end_date) as (
    select id, income, trunc(start_date, 'MM'), trunc(end_date, 'MM') 
    from your_table 
    union all 
    select id, income, this_date + interval '1' month, end_date 
    from r 
    where end_date > this_date 
) 
select id, income, to_char(this_date, 'MM/YYYY') as month 
from r 
order by id, this_date desc; 

     ID  INCOME MONTH 
---------- ---------- ------- 
     1  2000 05/2016 
     1  2000 04/2016 
     1  2000 03/2016 
     1  2000 02/2016 
     1  1500 01/2016 
     1  1500 12/2015 
     2  1000 04/2016 
     2  1000 03/2016 
     2  1000 02/2016 
     2  1000 01/2016 

锚成员得到的信息开始 - 我在截至本月初截断,可能是多余的,但以防万一本月开始时间足够晚,导致间隔增加的问题。递归成员继续向每个现有成员添加一个月,直到达到结束日期。

+0

谢谢Alex!他们都相应地工作。 –

+0

如果你有很多数据检查哪个性能更好,我怀疑connect-by会稍微快一点,尽管它可能会因大量数据而失败。 (呃,我想,在某些时候,这也是可以的!) –

相关问题