【问题标题】:Teradata/SQL : How to compare dates in consecutive rows using teradata SQL and write case statement on the resultTeradata/SQL:如何使用 teradata SQL 比较连续行中的日期并在结果上编写 case 语句
【发布时间】:2018-11-16 02:12:27
【问题描述】:

我需要将第一行中的日期(end dt)与第二行中的日期(strt dt)进行比较,如果匹配,我需要获取第二行的 strt dt。 如果它不匹配,我需要拿起第一行的 strt dt。一个订阅和频道包可以有多行。 我发现很难在 teradata 中编写查询以获得所需的输出。

以下是案例和预期结果。

案例一

Subscription    Channel package Start dt    End dt
11111112    Sports  7/3/2015    11/28/2015
11111112    Sports  4/1/2016    11/23/2016
11111112    Sports  11/23/2016  12/17/2017

需要输出

Subscription    Channel package Start dt    End dt
11111112    Sports  4/1/2016    12/17/2017

案例二

Subscription    Channel package Start dt    End dt
11111112    Sports  7/3/2015    11/28/2015
11111112    Sports  11/28/2015  4/1/2016
11111112    Sports  4/1/2016    11/23/2016
11111112    Sports  11/23/2016  12/17/2017

需要输出

Subscription    Channel package Start dt    End dt
11111112    Sports  7/3/2015    12/17/2017

我试过了

MIN(Start dt) OVER (PARTITION BY Subscription   , Channel package   
                    ORDER BY Start dt ROWS BETWEEN 1 FOLLOWING  AND 1 FOLLOWING
                   ) AS NXT Start dt

但由于我在使用资格时遇到了一些问题,所以无法走得更远。

【问题讨论】:

  • 窗口函数不会减少行数。你的问题不清楚。不满足条件的行会发生什么情况?如果顺序多行满足条件怎么办?您真正想要完成什么?
  • 是的,所以如果多行满足第 2 行 strt dt 与第 1 行 end dt 匹配的条件,这确实意味着订阅的频道包没有结束并且它是错误关闭的,那么我想要开始日期的最小值。但是,如果最后一个结束和下一个开始之间存在差距,那么它是一个正确的结束,我想要它下一个开始的日期。结果中应该有订阅和频道包组合的一行。
  • 这个问题真的不清楚。我建议你删除这个问题(它没有答案)。问另一个问题。提供一个包含三个左右不同示例的表格。显示您想要的结果。解释将行组合在一起的逻辑。 “与下一行比较”的概念并不完全符合您的要求。
  • Aniket 似乎正在寻求折叠基于订阅和频道包的连续序列链。我认为这可以通过窗口聚合和派生表来完成,我只是没有时间在 Teradata 实例中模拟数据。

标签: sql teradata


【解决方案1】:

我知道这可能是一个较晚的解决方案,也可能不是最快的解决方案。 我会这样开始:

(
     SELECT
             TBL.SUBSCRIPTION
         ,   TBL.CHANNEL
         ,   TBL.SUBSCRIPTION || TBL.CHANNEL AS SUB_CHANNEL
         ,   CASE WHEN TBL.END_DT = TBL.START_DT THEN 1 ELSE 0 END AS SAME_DAY_FLAG
         ,   Dense_Rank() Over (ORDER BY SUB_CHANNEL ) AS GRP_RANK
         ,   TBL.START_DT
         ,   TBL.END_DT
         ,   PERIOD(TBL.START_DT, CASE WHEN TBL.END_DT > DATE THEN DATE ELSE TBL.END_DT + 1 END) AS COVERD_DTES
         
     FROM    <YOUR_TABLE> AS TBL
) WITH DATA
ON COMMIT PRESERVE ROWS;

根据需要创建索引。创建SUB_CHANNEL 的原因是由于某些愚蠢的原因,我无法将手指放在上面,对于下面的某些功能,我无法拉出超过一列。


/* Create a table that will contain the Merged rows with proper start and end dates combining adjacent periods*/

CREATE VOLATILE TABLE VT_TBL_MERGED_ROWS AS
(
    WITH  CTE (GRP_RANK, COVERD_DTES) AS
    (
        SELECT 
                GRP_RANK, COVERD_DTES
        FROM VT_PRE_CTE 
        
    )
    SELECT * FROM TABLE
    (    
        TD_SYSFNLIB.Td_Normalize_Overlap_Meet(NEW VARIANT_TYPE( CTE.GRP_RANK),  CTE.COVERD_DTES)
        RETURNS (GRP_RANK INT, COVERD_DTES PERIOD(DATE))
        HASH BY  GRP_RANK
        LOCAL ORDER BY GRP_RANK, COVERD_DTES
     )  AS TBL_ROWS
    
)   WITH DATA
PRIMARY INDEX (GRP_RANK);

函数TD_SYSFNLIB.Td_Normalize_Overlap_Meet 标准化重叠的结束日期和开始日期,并分别为您提供最低和最后开始日期和结束日期的单行。由于我无法理解传递多列的方法,因此我创建了 GRP_RANK,然后我可以将其绑定。


CREATE VOLATILE TABLE VT_PRE_OUTPUT AS 
(SELECT 
                A.SUBSCRIPTION
            ,   A.CHANNEL
            ,   A.GRP_RANK
            ,   B.COVERD_DTES
            ,   Min(A.EFF_DT) AS EFF_DT
            ,   Max(A.EXP_DT) AS EXP_DT
            ,   End(B.COVERD_DTES)- Begin(B.COVERD_DTES) AS TOTAL_DAYS
        FROM    VT_PRE_CTE AS A
        JOIN    VT_TBL_MERGED_ROWS AS B
        ON      A.GRP_RANK = B.GRP_RANK 
        AND     A.COVERD_DTES OVERLAPS B.COVERD_DTES
        GROUP BY 1,2,3) 
        WITH DATA 
        PRIMARY INDEX(MTN,  EXP_DT)
        ON COMMIT PRESERVE ROWS;

如果SUBSCRIPTION/CHANNEL 组合之间有中断,这个A.COVERD_DTES OVERLAPS B.COVERD_DTES 实际上会给你多行。 您可以决定如何处理多个片段,使用QUALIFY Row_Number() OVER(PARTITION BY SUBSCRIPTION, CHANNEL ORDER BY MIN_DT ASC) = 1 获取第一次出现或使用ORDER BY MIN_DT DESC) 获取最新出现。

【讨论】:

    猜你喜欢
    • 2016-08-03
    • 1970-01-01
    • 2019-05-22
    • 2018-07-04
    • 2014-12-20
    • 2021-09-08
    • 2013-08-18
    • 2018-07-10
    • 2019-03-31
    相关资源
    最近更新 更多