我需要根据会计年度的begin_dt和end_dt将每一行分成x行。
这可以在oracle中完成吗?
我使用的脚本 如您所见,它们不是动态的。每个pp列都有大量的复制和粘贴操作,我需要提前了解我的数据。
- 如果没有任何选择,如何将数据移至列中并放入行中?
- 将要解决这个问题?
这是基本表
ANIMAL BEGIN_DT END_DT
-------- --------- ----------
dog 9/1/2017 6/30/2018
pig 7/15/1999 5/28/2001
cat 3/1/2018 1/27/2020
这是我到目前为止所拥有的
ANIMAL ORG_BEGIN_DT ORG_END_DT BP1 B1 E1 BP2 B2 E2 BP3 B3 E3
---- ------------ ------------ ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
dog 09/01/2017 09/01/2017 FY2018 09/01/2017 06/30/2018
pig 07/15/1999 07/15/1999 FY2000 07/15/1999 06/30/2000 FY2001 07/01/2000 05/28/2001
cat 03/01/2018 03/01/2018 FY2018 03/01/2018 06/30/2018 FY2019 07/01/2018 06/30/2019 FY2019 07/01/2019 01/27/2020
SET LINESIZE 32000;
column animal format a6
column ORG_BEGIN_DT format a12
column ORG_END_DT format a12
column BP1 format a10
column BP2 format a10
column BP3 format a10
column B1,B2,B3 format a17
column E1,E2,E3 format a17
CREATE TABLE SRCTBL (ANIMAL VARCHAR2(25) NOT NULL,
PERIOD_ID VARCHAR2(12) NOT NULL,
BEGIN_DT DATE,
END_DT DATE)
/
insert into SRCTBL values ( 'dog', ' ', to_date('9/1/2017','MM/DD/YYYY') , to_date('6/30/2018','MM/DD/YYYY' ));
insert into SRCTBL values ( 'pig', ' ', to_date('7/15/1999','MM/DD/YYYY'), to_date('5/28/2001','MM/DD/YYYY' ));
insert into SRCTBL values ( 'cat', ' ', to_date('3/1/2018','MM/DD/YYYY') , to_date('1/27/2020','MM/DD/YYYY' ));
commit;
with awrd as (select * from SRCTBL )
, pr as (select w.animal
, extract (month from w.begin_dt) begin_mon
, extract (month from w.end_dt) end_mon
, round(MONTHS_BETWEEN (w.end_dt ,w.begin_dt)) mth_dur
, round((w.end_dt - w.begin_dt)/365, 2) yr_dur
, case when extract ( month from w.begin_dt ) in (7,8,9,10,11,12)
then extract ( year from w.begin_dt ) + 1
else extract ( year from w.begin_dt ) end begin_yr
, case when extract ( month from w.end_dt ) in (7,8,9,10,11,12)
then extract ( year from w.end_dt ) + 1
else extract ( year from w.end_dt ) end AS end_yr
from SRCTBL w )
, calc as ( select pr.animal, begin_mon, end_mon , mth_dur , yr_dur ,begin_yr, end_yr from pr)
, pp1 as ( select calc.animal
, 'GFY-' || calc.begin_yr Budget_Period
, awrd.begin_dt
, case when calc.begin_mon >= 7 and calc.begin_yr = calc.end_yr and calc.end_mon > 6 then awrd.end_dt
when calc.begin_mon >= 7 and calc.begin_yr = calc.end_yr and calc.end_mon < 7 then awrd.end_dt
when calc.begin_mon >= 7 and calc.begin_yr <> calc.end_yr and calc.end_mon <= 7 then LAST_DAY ('30-JUN-'|| calc.begin_yr )
when calc.begin_mon >= 7 and calc.begin_yr <> calc.end_yr and calc.end_mon > 7 then LAST_DAY ('30-JUN-'|| calc.begin_yr )
when calc.begin_mon < 7 and awrd.end_dt > LAST_DAY ('30-JUN-'|| calc.begin_yr) then LAST_DAY ('30-JUN-'|| calc.begin_yr )
else awrd.end_dt end end_dt
from calc, awrd
where calc.animal= awrd.animal)
, pp2 as ( select pp1.animal
, case when awrd.end_dt = pp1.end_dt then NULL else 'GFY-' || to_char(to_number (calc.begin_yr) + 1) end Budget_Period
, case when awrd.end_dt = pp1.end_dt then NULL else pp1.end_dt + 1 end begin_dt
, case when awrd.end_dt = pp1.end_dt then NULL
when awrd.end_dt < LAST_DAY ('30-JUN-'|| to_char(to_number (calc.begin_yr) + 1)) then awrd.end_dt
else LAST_DAY ('30-JUN-'|| to_char(to_number (calc.begin_yr) + 1)) end end_dt
from pp1 , calc , awrd
where calc.animal = awrd.animal
and calc.animal = pp1.animal )
, pp3 as ( select pp2.animal
, case when awrd.end_dt = pp2.end_dt then NULL
when pp2.end_dt is null then NULL
else 'GFY-' || to_char(to_number (calc.begin_yr) + 1) end Budget_Period
, case when awrd.end_dt = pp2.end_dt then NULL else pp2.end_dt + 1 end begin_dt
, case when awrd.end_dt = pp2.end_dt then NULL
when pp2.end_dt is null then NULL
when awrd.end_dt < LAST_DAY ('30-JUN-'|| to_char(to_number (calc.begin_yr) + 2)) then awrd.end_dt
else LAST_DAY ('30-JUN-'|| to_char(to_number (calc.begin_yr) + 2)) end end_dt
from pp2 , calc , awrd
where calc.animal = awrd.animal
and calc.animal = pp2.animal )
select a.animal TYPE
, a.begin_dt, a.end_dt
, pp1.budget_period, pp1.begin_dt, pp1.end_dt
, pp2.budget_period, pp2.begin_dt, pp2.end_dt
, pp3.budget_period, pp3.begin_dt, pp3.end_dt
from awrd A , pp1, pp2, pp3
where a.animal = pp1.animal
and a.animal = pp2.animal
and a.animal = pp3.animal;
这是我需要的结果
ANIMAL FISCAL_YEAR BEGIN_DT END_DT
-------- --------- ---------- ----------
dog FY2018 9/1/2017 6/30/2018
pig FY2000 7/15/1999 6/30/2000
pig FY2001 7/1/2000 5/28/2001
cat FY2018 3/1/2018 6/30/2018
cat FY2019 7/1/2018 6/30/2019
cat FY2020 7/1/2019 1/27/2020
谢谢@Hanna,它有用。
select s.animal , 'GFY-' || extract ( year from fy.end_dt ) period_id
, case when s.begin_dt > fy.begin_dt then s.begin_dt else fy.begin_dt end begin_dt
, case when s.end_dt > fy.end_dt then fy.end_dt else s.end_dt end end_dt
from srctbl s, fiscal_years fy
where (( s.begin_dt between fy.begin_dt and fy.end_dt )
or ( s.end_dt between fy.begin_dt and fy.end_dt )
or ( s.begin_dt < fy.begin_dt and s.end_dt > fy.end_dt ))
order by 1,2;```
答案 0 :(得分:0)
这就是我要做的。基本上,您需要会计年度的行来源。在这里,我正在Common Table Expression中即时执行此操作。 (我将会计年度的范围设置得比必要的要大一些,因为我太懒了,无法进行数学计算。)您还可以创建一个显式表。
with fiscal_years as (
select 'FY' || to_char(1995+level) as fy_name,
to_date( '07/01/' || to_char(1995+level-1), 'MM/DD/YYYY' ) as begin_dt,
to_date( '06/30/' || to_char(1995+level), 'MM/DD/YYYY' ) as end_dt
from dual
connect by level <= 40
)
select s.animal, fy.begin_dt, fy.end_dt
from srctbl s
inner join fiscal_years fy
on ( s.begin_dt between fy.begin_dt and fy.end_dt )
or ( s.end_dt between fy.begin_dt and fy.end_dt )
or ( s.begin_dt < fy.begin_dt and s.end_dt > fy.end_dt )