暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 如何比较第一行和第二行的日期持续时间等等 ..并将其转换为带有指示符的行到列

ASKTOM 2018-12-13
517

问题描述

嗨,汤姆,
我有下表

CREATE TABLE PRDCT (ID NUMBER(10,0), 
PRDCT_CD VARCHAR2(1), 
START_DT DATE,
END_DT DATE);


像这样的数据-
Insert Into PRDCT Values (1,'A',to_date('01-May-2017'),to_date('31-Jul-2017'))
Insert Into PRDCT Values (1,'B',to_date('01-May-2017'),to_date('31-Aug-2017'))
Insert Into PRDCT Values (1,'C',to_date('01-May-2017'),to_date('31-Dec-9999'))

SELECT * FROM PRDCT;

ID   PRDCT_CD   START_DT     END_DT
--------------------------------------
1    A          01-MAY-17    31-JUL-17
1    B          01-MAY-17    31-Aug-17
1    C          01-May-17    31-Dec-99


我正在寻找以下结果:

ID  A_PRDCT_IND   B_PRDCT_IND   C_PRDCT_IND  START_DT   END_DT
-----------------------------------------------------------------
1   Y             Y             Y            01-MAY-17  31-JUL-17
1   N             Y             Y            01-Aug-17  31-Aug-17
1   N             N             Y            01-Sep-17  31-Dec-99


由于所有3个产品在31-7月-17之前都处于活动状态,因此第一行应将所有指示器显示为 “y”。产品 “B” 和 “c” 的下一行应显示第一行的START_DT = END_DT 1的指示器 “y”,直到产品B的结束日期为止,因为两者都在31-8月-17之前处于活动状态,依此类推...

我尝试使用以下枢轴解决方案,但没有运气。

SELECT ID,
CASE WHEN PRDCT_A = 'A' THEN 'Y' ELSE 'N' END AS A_PRDCT_IND,
CASE WHEN PRDCT_B = 'B' THEN 'Y' ELSE 'N' END AS B_PRDCT_IND,
CASE WHEN PRDCT_C = 'C' THEN 'Y' ELSE 'N' END AS C_PRDCT_IND,
START_DT,
END_DT
FROM PRDCT
PIVOT(MAX(PRDCT_CD) FOR PRDCT_CD IN ('A' PRDCT_A, 'B' PRDCT_B, 'C' PRDCT_C))


如果你提供一个动态的解决方案,将是非常感激的。

专家解答

如果要显示所有可能的开始/结束周期以及每个周期中的活动代码,则可以:

-将开始/结束日期调整为单个日期列表。返回不同的日期
-通过返回日期和下一个日期 (带有潜在客户) 将其转换回开始/结束期间
-外部根据每个开始/结束周期中的产品将产品加入其中
-根据要显示的产品代码对行进行旋转。在聚合中,如果代码为非空,则返回 'Y'
-将空标志映射到N,并进行一些日期调整以获取要关闭的范围-关闭间隔

with dates as ( 
  select distinct dt 
  from   prdct
  unpivot ( 
    dt for col in ( start_dt, end_dt )
  ) 
), ranges as (
  select dt start_dt, 
         lead ( dt ) over ( order by dt ) end_dt
  from   dates
), grps as (
  select p.prdct_cd, p.id, d.start_dt, d.end_dt
  from   ranges d
  left join prdct p
  on     p.start_dt <= d.start_dt
  and    p.end_dt >= d.end_dt
), rws as (
  select g.*, 
         row_number () over ( 
           partition by prdct_cd 
           order by start_dt 
         ) rn
  from   grps g
  where  end_dt is not null
)
  select id, start_dt + case when rn = 1 then 0 else 1 end start_dt, end_dt, 
         nvl ( a, 'N' ) a, 
         nvl ( b, 'N' ) b, 
         nvl ( c, 'N' ) c 
  from   rws 
  pivot (
    max ( case when prdct_cd is not null then 'Y' end )
    for  prdct_cd in ( 'A' a, 'B' b, 'C' c)
  )
  order  by start_dt;

ID   START_DT               END_DT                 A   B   C   
   1 01-MAY-2017 00:00:00   31-JUL-2017 00:00:00   Y   Y   Y   
   1 01-AUG-2017 00:00:00   31-AUG-2017 00:00:00   N   Y   Y   
   1 01-SEP-2017 00:00:00   31-DEC-9999 00:00:00   N   N   Y  

文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论