一尘不染

如何根据列调整日期和不同的记录

sql

REG_ID| EVENT_TYPE_CD    | EVENT_DATE | PACKAGE_DESC    |PRODUCT_TYPE|TERM_START_DATE|TERM_END_DATE  
------|------------------|------------|-----------------|------------|---------------|----------

11156 | NEW SUBSCRIPTION |  23-FEB-16 | CONNECTED CARE  |PAID        | 23-FEB-16     | 23-FEB-16  
11156 | CANCELLATION     |  23-FEB-16 | CONNECTED CARE  |PAID        | 23-FEB-16     | 23-FEB-16  
11156 | UPSELL           |  23-FEB-16 | CONNECTED CARE  |GOODWILL    | 23-FEB-16     | 22-MAR-16  
11156 | CANCELLATION     |  11-MAR-16 | CONNECTED CARE  |GOODWILL    | 23-FEB-16     | 11-MAR-16  
11156 | UPSELL           |  14-MAR-16 | CONNECTED CARE  |GOODWILL    | 14-APR-16     | 13-APR-17  
11156 | EXPIRATION       |  14-APR-16 | CONNECTED CARE  |GOODWILL    | 14-MAR-16     | 13-APR-17  
11163 | UPSELL           |  23-FEB-16 | CONNECTED CARE  |PAID        | 23-FEB-16     | 23-FEB-16  
11163 | CANCELLATION     |  23-FEB-16 | CONNECTED CARE  |PAID        | 23-FEB-16     | 22-MAR-16    
17215 | NEW SUBSCRIPTION |  18-JAN-16 | CONNECTED CARE  |TRIAL       | 18-JAN-16     | 17-JAN-17  
17215 | NEW SUBSCRIPTION |  18-JAN-16 | GUIDANCE        |TRIAL       | 18-JAN-16     | 17-APR-16  
17215 | CANCELLATION     |  22-FEB-16 | GUIDANCE        |TRIAL       | 18-JAN-16     | 22-FEB-16  
17215 | UPSELL           |  25-FEB-16 | GUIDANCE        |GOODWILL    | 25-FEB-16     | 24-APR-16  
17215 | EXPIRATION       |  25-APR-16 | GUIDANCE        |GOODWILL    | 25-FEB-16     | 24-APR-16  
17215 | NEW SUBSCRIPTION |  18-JAN-16 | REMOTE          |TRIAL       | 18-JAN-16     | 17-APR-16  
17215 | UPSELL           |  25-FEB-16 | REMOTE          |GOODWILL    | 25-FEB-16     | 24-APR-16  
17215 | NEW SUBSCRIPTION |  18-JUN-16 | REMOTE          |PAID        | 18-JUN-16     | 17-JUL-16  
17215 | UPSELL           |  25-JUL-16 | REMOTE          |GOODWILL    | 25-JUL-16     | 24-AUG-16

我需要的输出是所有内容都需要按EVENT_DATE(事件系列)进行排序

  1. 如果“商誉” EVENT_DATE在“试用”产品EVENT_DATE之后,则将其视为“试用”。如果“商誉” EVENT_DATE跟在“已付费”产品EVENT_DATE之后,则将其视为“已付费”并调整TERM_END_DATE(当REG_ID中的特定PACKAGE_DESC没有取消或EXPIRATION event_type_cd时,REMOTE理想方案的示例)

  2. 如果取消后有事件,则忽略取消(11163出现:这是因为取消后没有新事件)

  3. 如果跟踪中有多个商誉,我们需要将周期中的最大TERM_END_DATE分配为TERM_END_DATE(REG_ID 17215和GUIDANCE)。

  4. EXPIRATION RECORD应该一直存在,并且必须将其term_start_date调整为周期第1条记录的Term_start_date。

    REG_ID EVENT_TYPE_CD EVENT_DATE PACKAGE_DESC PRODUCT_TYPE TERM_START_DATE TERM_END_DATE

    11156 | NEW SUBSCRIPTION | 23-FEB-16 | CONNECTED CARE |PAID | 23-FEB-16 | 13-APR-17
    11156 | EXPIRATION | 14-APR-16 | CONNECTED CARE |PAID | 23-FEB-16 | 13-APR-17
    11163 | UPSELL | 23-FEB-16 | CONNECTED CARE |PAID | 23-FEB-16 | 23-FEB-16
    11163 | CANCELLATION | 23-FEB-16 | CONNECTED CARE |PAID | 23-FEB-16 | 22-MAR-16
    17215 | NEW SUBSCRIPTION | 18-JAN-16 | CONNECTED CARE |TRIAL | 18-JAN-16 | 17-JAN-17
    17215 | NEW SUBSCRIPTION | 18-JAN-16 | GUIDANCE |TRIAL | 18-JAN-16 | 24-APR-16
    17215 | EXPIRATION | 25-APR-16 | GUIDANCE |TRAIL | 18-JAN-16 | 24-APR-16
    17215 | NEW SUBSCRIPTION | 18-JAN-16 | REMOTE |TRIAL | 18-JAN-16 | 24-APR-16
    17215 | NEW SUBSCRIPTION | 18-JUN-16 | REMOTE |PAID | 18-JUN-16 | 24-AUG-16


阅读 143

收藏
2021-05-16

共1个答案

一尘不染

这些规则非常广泛,使用PL / SQL代码可能会获得更好的结果和性能,因为在游标上迭代时可以使用变量。

不过,我认为以下查询可能会满足您的需求:

select  reg_id, 
        event_type_cd,
        event_date,
        package_desc,
        case product_type when 'GOODWILL' then coalesce(prev_product_type, 'TRIAL')
            else product_type
        end as product_type,
        case event_type_cd when 'EXPIRATION' then first_term_start_date
            else term_start_date
        end as term_start_date,
        case next_product_type when 'GOODWILL' then next_term_end_date
            else term_end_date
        end as term_end_date
from    (select reg_id, 
                event_type_cd,
                event_date,
                package_desc,
                product_type,
                term_start_date,
                term_end_date,
                first_value(term_start_date) over (
                    partition by reg_id, package_desc 
                    order by event_date, term_end_date, event_type_cd desc) as first_term_start_date,
                lead(term_end_date, 1) over (
                    partition by reg_id, package_desc 
                    order by event_date, term_end_date, event_type_cd desc) as next_term_end_date,
                lag(product_type, 1) over (
                    partition by reg_id, package_desc 
                    order by event_date, term_end_date, event_type_cd desc) as prev_product_type,
                lead(product_type, 1) over (
                    partition by reg_id, package_desc 
                    order by event_date, term_end_date, event_type_cd desc) as next_product_type
        from    (select reg_id, 
                        event_type_cd,
                        event_date,
                        package_desc,
                        product_type,
                        term_start_date,
                        term_end_date,
                        lead(product_type, 1, '-') over (
                            partition by reg_id, package_desc 
                            order by event_date, term_end_date, event_type_cd desc) as next_product_type
                from    mytable)
                where   not (event_type_cd = 'CANCELLATION' and next_product_type <> '-')
                and     not (product_type = 'GOODWILL' and next_product_type = 'GOODWILL')
                )
where    not (    product_type = 'GOODWILL' 
              and event_type_cd not in ('EXPIRATION', 'CANCELLATION') 
              and prev_product_type is not null)
order by reg_id, package_desc, event_date, term_end_date, event_type_cd desc

该查询具有两级嵌套子查询。

最里面的查询 只用于获得 PRODUCT_TYPE 周期(即在同一分区内中的下一个记录的 REG_IDpackage_desc
)。

中间的查询 使用该信息来消除:

  • “取消”记录,除非它们是其周期的最后一个记录;
  • 连续的“ GOODWILL”记录,在每个序列中仅保留最后一个-这是最后一个是临时的,但在此阶段仍需要;

中间查询还重新获取循环中下 一条 记录的 product_type ,因为由于删除了记录,现在它可能已更改。此外,它确定:

  • 循环 中第一条记录的 term_start_date
  • 周期中下 一条 记录的 term_end_date
  • 循环中前一个记录的 product_type

最后, 外部查询 使用此信息来:

  • 如果涉及到“ GOODWILL”记录,则将 product_type 设置为先前记录的记录(如果没有先前记录,则设置为“ TRIAL”);
  • 如果涉及到“ EXPIRATION”记录,则将 term_start_date 设置为循环中第一条记录的记录;
  • 如果下一条记录涉及“ GOODWILL”记录,则将 term_end_date 设置为周期中下一条记录的term_end_date。

“ GOODWILL”记录(在上述第一个项目符号发生更改之前)从结果中排除,除非它们与循环中的第一个记录相关或与“ EXPIRATION”或“
CANCELLATION”记录相对应。

order by子句使用您在注释中提到的顺序,另外event_type_cd desc还要确保
“用于取消或到期的EVENT_TYPE_CD始终遵循特定的REG_ID PACKAGE_DESC的新订阅或UPSELL” 。这是因为幸运的是,“ NEW
SUBSCRIPTION”和“ UPSELL”都比“ CANCELLATION”和“
EXPIRATION”的字母顺序都晚,所以按降序排列就可以对它们进行正确排序。

2021-05-16