Oracle SQL如何根据日期范围按月分解收入?

时间:2017-02-23 04:25:26

标签: sql oracle oracle11g

试图根据表A中的数据找到一种有效的方法来实现下表B中的结果。假设一个表A中有数百万个这样的记录,是否存在这样做的有效方式(即资源不足)?请注意,ID 1的结束日期为12/31/2199(不是拼写错误),我们仅列出2016年9月至2016年12月期间每个ID的收入。另请注意,ID 3在2016年11月有两个收入,600表示11月收入(因为这是ID在2016年11月底的收入)。至于在2016年11月开始的ID,由于它们在11月之前不存在,它们的行将在9月16日和10月16日丢失。

表A:


ID  INCOME  EFFECTIVE_DATE  END_DATE
1   700     07/01/2016      12/31/2199
2   500     08/20/2016      12/31/2017
3   600     11/11/2016      02/28/2017
3   100     09/01/2016      11/10/2016
4   400     11/21/2016      12/31/2016

表B(预期结果):

         
ID  INCOME  MONTH
1   700     12/2016
1   700     11/2016
1   700     10/2016
1   700     09/2016
2   500     12/2016
2   500     11/2016
2   500     10/2016
2   500     09/2016
3   600     12/2016
3   600     11/2016
3   100     10/2016
3   100     09/2016
4   400     12/2016
4   400     11/2016

已解决我使用了下面@mathguy提供的答案,它就像一个魅力 - 在这个过程中学到了新的东西:pivot和unpivot。还要感谢@MTO(以及其他所有人)花时间提供帮助。

1 个答案:

答案 0 :(得分:2)

这是一个解决方案,它只使用基表中的每一行,并且不需要连接,分组等。它使用自Oracle 11.1以来可用的unpivot操作,这不是一项昂贵的操作

with
     table_a ( id, income, effective_date, end_date ) as (
       select 1, 700, date '2016-07-01', date '2199-12-31' from dual union all
       select 2, 500, date '2016-08-20', date '2017-12-31' from dual union all
       select 3, 600, date '2016-11-11', date '2017-02-28' from dual union all
       select 3, 100, date '2016-09-01', date '2016-11-10' from dual union all
       select 4, 400, date '2016-11-21', date '2016-12-31' from dual
     )
-- end of test data (not part of the solution): SQL query begins BELOW THIS LINE
select id, income, mth
from (
       select id,
              case when date '2016-09-30' between effective_date and end_date
                   then income end as sep16,
              case when date '2016-10-31' between effective_date and end_date
                   then income end as oct16,
              case when date '2016-11-30' between effective_date and end_date
                   then income end as nov16,
              case when date '2016-12-31' between effective_date and end_date
                   then income end as dec16
       from   table_a
     )
unpivot ( income for mth in ( sep16 as '09/2016', oct16 as '10/2016', nov16 as '11/2016',
                              dec16 as '12/2016' )
        )
order by id, mth desc
;

<强>输出

ID INCOME MTH
-- ------ -------
 1    700 12/2016
 1    700 11/2016
 1    700 10/2016
 1    700 09/2016
 2    500 12/2016
 2    500 11/2016
 2    500 10/2016
 2    500 09/2016
 3    600 12/2016
 3    600 11/2016
 3    100 10/2016
 3    100 09/2016
 4    400 12/2016
 4    400 11/2016

14 rows selected.