Recursion 如何基于同一列中的上一行值计算行值

Recursion 如何基于同一列中的上一行值计算行值,recursion,updates,teradata,Recursion,Updates,Teradata,我有以下数据集: DATE CODE RANK PARTITION ? ABS 0 1 12/04/2014 RET 1 1 20/04/2014 RET 2 1 01/05/2014 ABS 2 1 13/05/2014 RET 2 1 01/06/2015 ABS

我有以下数据集:

     DATE   CODE    RANK    PARTITION
       ?    ABS        0           1
 12/04/2014 RET        1           1
 20/04/2014 RET        2           1
 01/05/2014 ABS        2           1
 13/05/2014 RET        2           1
 01/06/2015 ABS        2           1
 09/10/2015 RETk       2           1
         ?  ABS        0           2
 02/04/2015 RET        1           2
 03/04/2015 RET        2           2
 04/04/2015 ABS        2           2
 05/04/2015 STT        3           2
 06/04/2015 RETk       4           2
 07/04/2015 RETk       4           2
RANK是给定列DATE、CODE和同一列的上一个值的SQL中要计算的列。它在这里初始化为0。 我想实现的逻辑如下:

 If RANK-1 (previous row) IS NULL AND CODE = ABS THEN RANK = 0
 If RANK-1 (previous row) IS NULL AND CODE <> ABS THEN RANK <- (RANK-1) + 1
 If RANK-1 = 0 or 1 AND CODE = RET THEN RANK <-  (RANK-1) + 1
 If RANK-1 = 2 AND CODE = STT THEN RANK <- (RANK-1) + 1
 If RANK-1 = 3 AND CODE = RETk THEN RANK <-  (RANK-1) + 1
 If CODE = ABS THEN RANK <- (RANK-1) (previous row)
 Else 0
如果秩-1(前一行)为空且code=ABS,则秩=0

如果秩-1(前一行)为空并编码为ABS,则秩如下:

create table table1
(
  datecol date,
  code varchar(10),
  rankcol integer
);     
--insert into table1 select '2014/05/13', 'RETj', 0;

select 
  case 
  when s1.code='ABS' and s2.rankcol = 1 then 1
  when s1.code='RET' and s2.rankcol = 0 then 1
  when s1.code='RET' and s2.rankcol = 1 then 2
  else 0
  end RET_res,
  s1.*, s2.*
from
(select rankcol, code, row_number() OVER (order by datecol) var1 from table1) s1,
(select rankcol, code, row_number() OVER (order by datecol) var1 from table1) s2
where s1.var1=s2.var1-1
order by s1.var1  
; 

对于这样的任务,您始终可以使用递归查询。但是,除非每个组的行数很低,否则性能会很差

首先,您需要一种前进到下一行的方式,因为下一行的日期无法根据当前行的日期计算,因此您必须具体化数据并添加行号:

CREATE TABLE tab(dt DATE, CODE VARCHAR(10), rnk INT, part INT);

INSERT INTO tab(            NULL,'ABS' ,0 ,          1);
INSERT INTO tab(DATE'2014-04-12','RET' ,1 ,          1);
INSERT INTO tab(DATE'2014-04-20','RET' ,2 ,          1);
INSERT INTO tab(DATE'2014-05-01','ABS' ,2 ,          1);
INSERT INTO tab(DATE'2014-05-13','RET' ,2 ,          1);
INSERT INTO tab(DATE'2014-06-01','ABS' ,2 ,          1);
INSERT INTO tab(DATE'2014-10-09','RETk',2 ,          1);
INSERT INTO tab(            NULL,'ABS' ,0 ,          2);
INSERT INTO tab(DATE'2015-04-02','RET' ,1 ,          2);
INSERT INTO tab(DATE'2015-04-03','RET' ,2 ,          2);
INSERT INTO tab(DATE'2015-04-04','ABS' ,2 ,          2);
INSERT INTO tab(DATE'2015-04-05','STT' ,3 ,          2);
INSERT INTO tab(DATE'2015-04-06','RETk',4 ,          2);
INSERT INTO tab(DATE'2015-04-07','RETk',4 ,          2);

CREATE VOLATILE TABLE vt AS
 (
   SELECT dt, code, part
     -- used to find the next row
     ,ROW_NUMBER() OVER (PARTITION BY part ORDER BY dt) AS rn
   FROM tab
 ) WITH DATA
PRIMARY INDEX(part, rn)
ON COMMIT PRESERVE ROWS
;
现在,它只是使用CASE一行接一行地应用您的逻辑:

WITH RECURSIVE cte (dt, code, rnk, part, rn) AS
 (
   SELECT
      dt
     ,code
     ,CASE WHEN code = 'ABS' THEN 0 ELSE 1 END
     ,part
     ,rn
   FROM vt
   WHERE rn = 1
   UNION ALL
   SELECT
      vt.dt
     ,vt.code
     ,CASE
         WHEN cte.rnk IN (0,1) AND vt.CODE = 'RET'  THEN cte.rnk + 1
         WHEN cte.rnk = 2      AND vt.CODE = 'STT'  THEN cte.rnk + 1
         WHEN cte.rnk = 3      AND vt.CODE = 'RETk' THEN cte.rnk + 1
         WHEN                      vt.CODE = 'ABS'  THEN cte.rnk
         ELSE cte.rnk
      END
     ,vt.part
     ,vt.rn
   FROM vt JOIN cte
     ON vt.part =cte.part
    AND vt.rn   =cte.rn + 1  
 ) 
SELECT *
FROM cte
ORDER BY part, dt;
但我认为您的逻辑实际上不是这样的(基于前几行的确切秩值),您只是停留在程序性思维中:-)


您可能只需要使用OLAP函数就可以执行所需操作…

您是否尝试过前面1到1之间的
行?添加您的查询,这样我们就可以看到您迄今为止所做的尝试。介于1和1之间的行无法解决问题,因为在此阶段列名未知:即使我这样做:min(RANK)over(按ID划分,按日期排列,介于1和1之间),RANK未被识别我在考虑在SQL查询中使用一个临时变量,存储前一行的值,以便在当前行计算中使用它…这有意义吗?如何使用前一行值更新用户定义的变量?是否可以添加更多行,并详细解释您想要的结果以及原因?rankcol是基于两个参数计算的:当前代码和前一个秩:除非前一行等于1且当前代码为1,否则当前行的秩不能增加等于一个特定的代码。它更像是状态机或递归模型。我在下面又增加了几个专栏,并做了更多的解释。希望这是清楚的谢谢你的答复。但是我不明白:您引用的rankcol列等于零,并且根本不更新。我需要的是返回上一行中先前计算的rankcol值,并将其作为输入来计算当前行中的rankcol,