基本上我有一行数据,例如:
ID - Start_Date - End_Date
------------------------------------
XXA 1/23/14 3/12/14
我希望在Start_Date
和End_Date
之间为每个ID
创建一行,例如:
ID - Month - Year
--------------------------
XXA January 2014
XXA February 2014
XXA March 2014
这是最好和最有效的方法吗?我正在考虑使用游标,但是一旦创建了这个表,我就需要将其他表加入到这个表中。我是oracle的新手,在运行游标并创建临时表后,我不确定是否可以加入其他表。任何帮助将不胜感激。
答案 0 :(得分:1)
您可以使用CONNECT BY
语法使用简单的行生成技术:
with sample_data as
(select 'XXA' id, to_date('1/23/14','MM/DD/RR') start_date, to_date('3/12/14','MM/DD/RR') end_date from dual)
select id, to_char(add_months(start_date,level - 1),'Month YYYY') date_column
from sample_data
connect by level <= extract(month from end_date) - extract(month from start_date) + 1;
修改强>
我相信,添加DISTINCT
应允许跨行工作,尽管我有兴趣被证明是错误的。
编辑2 修改后的例子来处理多年(最初应该这样做)。 (参见示例http://sqlfiddle.com/#!4/9eecb/4097/0。)
with sample_data as
( select 'XXA' id, to_date('1/23/14','MM/DD/RR') start_date, to_date('3/12/15','MM/DD/RR') end_date from dual union all
select 'XXB' id, to_date('4/12/14','MM/DD/RR') start_date, to_date('6/18/15','MM/DD/RR') end_date from dual )
select distinct
id,
to_char(add_months(start_date,level - 1),'Month YYYY') date_column,
add_months(start_date,level -1) sortkey
from sample_data
connect by level <= ceil(months_between(trunc(end_date,'MM'), trunc(start_date,'MM'))) + 1
order by id, sortkey;
在我的沙盒DB中,这会产生:
ID DATE_COLUMN SORT_COL
XXA January 2014 23-JAN-2014 00:00:00
XXA February 2014 23-FEB-2014 00:00:00
XXA March 2014 23-MAR-2014 00:00:00
XXB April 2014 12-APR-2014 00:00:00
XXB May 2014 12-MAY-2014 00:00:00
XXB June 2014 12-JUN-2014 00:00:00
答案 1 :(得分:0)
要获得预期结果,需要一些年月数据。我建议两种可能的方法来提供它:
其他选项假设隐含生成年度数据,我认为这不是一个好的,作为一个明显的直接解决方案。
第二个选项(理论上)可能在更大的输入数据上更快,但是我不推荐它,因为你没有提及性能,它比第一个更复杂。
最简单易用的解决方案是:
create table year (id int primary key);
insert into year values (2014);
insert into year values (2015);
insert into year values (2016);
create table month (id int primary key, name char(255));
insert into month values (1, 'Jan');
insert into month values (2, 'Feb');
insert into month values (3, 'Mar');
insert into month values (4, 'Apr');
insert into month values (5, 'May');
insert into month values (6, 'Jun');
insert into month values (7, 'Jul');
insert into month values (8, 'Aug');
insert into month values (9, 'Sep');
insert into month values (10, 'Oct');
insert into month values (11, 'Nov');
insert into month values (12, 'Dec');
create table data (id char(15) primary key , start_date date, end_date date);
insert into data
values ('XXA', to_date('1/23/14','MM/DD/RR'), to_date('3/12/14','MM/DD/RR'));
insert into data
values ('XXB', to_date('4/12/14','MM/DD/RR'), to_date('6/18/14','MM/DD/RR'));
create or replace view calendar as
select y.id*100 + m.id as id, y.id as year, m.name as month
from year y, month m;
select d.id, c.month, c.year
from calendar c, data d
where c.id between to_char(d.start_date, 'yyyymm')
and to_char(d.end_date, 'yyyymm');
输出结果为:
XXA|Jan|2014 ---+---+---- XXA|Feb|2014 ---+---+---- XXA|Mar|2014 ---+---+---- XXB|Apr|2014 ---+---+---- XXB|May|2014 ---+---+---- XXB|Jun|2014
提前填写Year表非常重要,否则它将一直运行到2016年。