如何-根据会计开始日期和结束日期选择其他行

时间:2019-08-28 22:09:00

标签: oracle

我需要根据会计年度的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;```

1 个答案:

答案 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 )

SQL Fiddle