【问题标题】:Aggregate periods using recursive queries使用递归查询聚合周期
【发布时间】:2019-01-23 13:29:09
【问题描述】:

我需要将每个组 (ID) 的连续事件(标识符为 NUM)的重叠时段(由 FROM 和 TO 变量定义)与“前瞻缓冲区”合并,这意味着如果下一个时段在缓冲区内开始,它们应该被合并。

例如;在以下示例中,第二个事件 (NUM = 2) 在时间 13 开始,该时间位于缓冲区 (10 + 5 = 15) 内。

与我发现的其他类似问题相比,这里的棘手部分是,虽然每个事件的缓冲期都有一个固定值,但如果它与具有更长缓冲的事件(仅向后)合并,这可能会发生变化期间。

例如;事件三也合并到与事件一和事件二相同的时期,因为这些事件的缓冲期更长。后面的缓冲区应该是 (25 + 5 = 30),而不是 (25 + 3 = 28),这意味着后面的事件 4 也应该包含在这些时间段中。

再次将事件4的缓冲期也改为5。但是因为40>31+5,所以最后一个事件是单独观察的。

CREATE TABLE MY_TABLE(ID INTEGER, NUM INTEGER, FROM INTEGER, TO INTEGER, LOOKAHEAD INTEGER);
INSERT INTO MY_TABLE VALUES (1, 1, 1,  10, 5);
INSERT INTO MY_TABLE VALUES (1, 2, 13, 20, 5);
INSERT INTO MY_TABLE VALUES (1, 3, 21, 25, 3);
INSERT INTO MY_TABLE VALUES (1, 4, 29, 31, 3);
INSERT INTO MY_TABLE VALUES (1, 5, 40, 50, 3);

最终,我需要的结果是两个“分离”周期的两个观察结果;

(ID = 1, FROM = 1,  TO = 31)
(ID = 5, FROM = 40, TO = 50)

当然,我最初认为我可以创建这个“LOOKHEAD”变量,方法是创建一个新变量 LOOKAHEAD2,它是 LOOKAHEAD2 的先前值和 LOOKAHEAD 的当前值的最大值,条件是 FROM(这条记录)

相反,我尝试使用递归查询,从第一个事件(NUM = 1) 开始,然后以(root.TO + root.LOOKAHEAD > next.FROM) 为条件将下一个事件(root.NUM+1 = next.NUM) 递归加入表,并相应地更新 LOOKAHEAD 变量。

但我以前从未使用过递归查询,我无法让它加入 LOOKAHEAD 值的更新值。

有谁知道如何通过递归查询或其他方式解决这个问题?

【问题讨论】:

    标签: teradata recursive-query teradata-sql-assistant


    【解决方案1】:

    您应该在分析函数中使用RESET WHEN 窗口修饰符(Teradata 16 中的LAG,或早期版本中的MAX);不要使用递归查询。

    更新:

    DROP TABLE MY_TABLE;
    CREATE VOLATILE TABLE MY_TABLE 
    ( id          INTEGER
    , num         INTEGER
    , from_value  INTEGER
    , to_value    INTEGER
    , lookahead   INTEGER
    ) ON COMMIT PRESERVE ROWS;
    
    INSERT INTO MY_TABLE VALUES (1, 1, 1,  10, 5);
    INSERT INTO MY_TABLE VALUES (1, 2, 13, 20, 5);
    INSERT INTO MY_TABLE VALUES (1, 3, 21, 25, 3);
    INSERT INTO MY_TABLE VALUES (1, 4, 29, 31, 3);
    INSERT INTO MY_TABLE VALUES (1, 5, 40, 50, 3);
    
    INSERT INTO MY_TABLE VALUES (2, 1, 1, 10, 5);
    INSERT INTO MY_TABLE VALUES (2, 2, 20, 30, 15);
    INSERT INTO MY_TABLE VALUES (2, 3, 40, 41, 5);
    INSERT INTO MY_TABLE VALUES (2, 4, 100, 200, 5);
    INSERT INTO MY_TABLE VALUES (2, 5, 300, 400, 3);
    
    
    SELECT  id, first_from_value, to_value
    FROM  ( SELECT  id
                  , to_value
                  , CASE WHEN overlaps_flag = 1
                      THEN  NULL
                      ELSE  COALESCE 
                            ( MIN (from_value) 
                                OVER (PARTITION BY id
                                      ORDER BY from_value
                                      RESET WHEN MAX (overlaps_flag) 
                                                   OVER (PARTITION BY id 
                                                         ROWS BETWEEN 
                                                              1 PRECEDING 
                                                          AND 1 PRECEDING) = 0
                                      ROWS BETWEEN UNBOUNDED PRECEDING 
                                               AND 1 PRECEDING)
                            , from_value )
                    END AS first_from_value
            FROM  ( SELECT  id, from_value, to_value
                          , MAX (from_value) 
                              OVER (PARTITION BY id 
                                    ORDER BY from_value 
                                    ROWS BETWEEN 1 FOLLOWING AND 1 FOLLOWING)
                              AS next_from_value
                          , CASE WHEN to_value + lookahead + 1 >= next_from_value
                              THEN 1 ELSE 0 
                            END AS overlaps_flag
                    FROM  my_table
                  ) AS a
          ) AS a
    WHERE first_from_value IS NOT NULL
    ORDER BY 1, 2
    
    id  first_from_value    to_value
    1   1                   31
    1   40                  50
    2   1                   10
    2   20                  41
    2   100                 200
    2   300                 400
    

    【讨论】:

    • 我用另一种语言导出后解决了。我看了RESET WHEN,这是我以前不知道的,谢谢。但是,我仍然看不到它将如何解决问题。如果你愿意,我很乐意看看你的解决方案。
    猜你喜欢
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 2016-10-13
    • 2014-03-01
    • 2014-04-09
    • 2014-03-23
    相关资源
    最近更新 更多