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

Oracle 第一个非零周期的需要日期

askTom 2017-09-08
282

问题描述

create table nsk_abc (i1 varchar2(100), L1 varchar2(100), startdate date, period1 number, period2 number, period3 number);

ALTER TABLE NSK_ABC ADD CONSTRAINT NSK_ABC_PK1 PRIMARY KEY (I1, L1);
 
insert into nsk_abc values ('I1','L1', DATE '2017-09-04', 10, 0, 11);

insert into nsk_abc values ('I1','L2', DATE '2017-08-28', 0, 0, 11);
  
insert into nsk_abc values ('I1','L3', DATE '2017-08-21', 0,12,11);

insert into nsk_abc values ('I1','L4', DATE '2017-09-04', 0,0,0);

CoMMIt;

SELECT * FROM NSK_ABC
  
I1      L1      STARTDATE   PERIOD1  PERIOD2  PERIOD3
-----------------------------------------------------
I1 L1 04-SEP-17 10 0 11
I1 L2 28-AUG-17 0 0 11
I1 L3 21-AUG-17 0 12 11
I1 L4 04-SEP-17 0 0 0  
 


Expected Output:

SELECT I1, L1, STARTDATE, PERIOD1, PERIOD2, PERIOD3, COALESCE(DECODE(PERIOD1,0,NULL,1), DECODE(PERIOD2,0,NULL,2), DECODE(PERIOD3,0,NULL,3)) FINAL_VAL, STARTDATE + ((COALESCE(DECODE(PERIOD1,0,NULL,1), DECODE(PERIOD2,0,NULL,2), DECODE(PERIOD3,0,NULL,3))) -1) * 7  FIRST_NON_ZERO_DATE FROM NSK_ABC
  
I1      L1      STARTDATE    PERIOD1  PERIOD2 PERIOD3 FINAL_VAL FIRST_NON_ZERO_DATE
----------------------------------------------------------------------------
I1 L1 04-SEP-17 10 0 11 1 04-SEP-17
I1 L2 28-AUG-17 0 0 11 3 11-SEP-17
I1 L3 21-AUG-17 0 12 11 2 28-AUG-17
I1 L4 04-SEP-17 0 0 0  -   -  
 


Period1 -> startdate
Period2-> startdate+ 7
Period3 -> startdate+ 14
复制



我们如何得出预期输出:

对于I1,L1 -> 第一个非零列为period1,值为10,日期为04-9月-2017,因此输出应为
对于I1,L2 -> 第一个non_zero列为Period3,值为11,日期为period3,因此将为dt1 3周,因此将为2017年9月11日,依此类推。

我正在获得预期的结果,但只是想是否还有其他方法可以实现这一目标:

a) 在我的情况下,周期将是1到104 (所以104列)
b) 将5000万表中的记录计数。

非常感谢,

专家解答

SQL在执行之前进行编译。列像变量,SQL不能动态索引列,像C不能索引它的标量变量。因此,除非您规范化您的架构 (将104列更改为104行),并且您希望保留在SQL中,而无需在PL/SQL或客户端代码中执行动态SQL技巧,否则您必须显式引用查询中的所有列以评估其值。因此,与已经编写的内容相比,您无法简化查询。对于更复杂的周期列值处理,UNPIVOT子句可能是有用的,尽管UNPIVOT并不便宜。对于您的简单要求,我将使用清晰的大小写表达式:

SELECT I1, L1, STARTDATE, PERIOD1, PERIOD2, PERIOD3,
       CASE WHEN PERIOD1 <> 0 THEN 1
            WHEN PERIOD2 <> 0 THEN 2
            WHEN PERIOD3 <> 0 THEN 3
            ...
            ELSE NULL END FINAL_VAL
       CASE WHEN PERIOD1 <> 0 THEN STARTDATE+0*7
            WHEN PERIOD2 <> 0 THEN STARTDATE+1*7
            WHEN PERIOD3 <> 0 THEN STARTDATE+2*7
            ...
            ELSE NULL END FIRST_NON_ZERO_DATE
FROM NSK_ABC;
复制


案例使用短路评估,并允许最多32K时/然后配对,远远超过表中的最大列数 (= 1000)。

根据您的使用情况,您可能会考虑计算插入时的最终值 (或当所有列都具有其值时),以避免多次运行此复杂查询。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论