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(事件系列)进行排序
如果“商誉” EVENT_DATE在“试用”产品EVENT_DATE之后,则将其视为“试用”。如果“商誉” EVENT_DATE跟在“已付费”产品EVENT_DATE之后,则将其视为“已付费”并调整TERM_END_DATE(当REG_ID中的特定PACKAGE_DESC没有取消或EXPIRATION event_type_cd时,REMOTE理想方案的示例)
如果取消后有事件,则忽略取消(11163出现:这是因为取消后没有新事件)
如果跟踪中有多个商誉,我们需要将周期中的最大TERM_END_DATE分配为TERM_END_DATE(REG_ID 17215和GUIDANCE)。
EXPIRATION RECORD应该一直存在,并且必须将其term_start_date调整为周期第1条记录的Term_start_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
这些规则非常广泛,使用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_ID 和 package_desc )。
在 中间的查询 使用该信息来消除:
中间查询还重新获取循环中下 一条 记录的 product_type ,因为由于删除了记录,现在它可能已更改。此外,它确定:
最后, 外部查询 使用此信息来:
“ GOODWILL”记录(在上述第一个项目符号发生更改之前)从结果中排除,除非它们与循环中的第一个记录相关或与“ EXPIRATION”或“ CANCELLATION”记录相对应。
该order by子句使用您在注释中提到的顺序,另外event_type_cd desc还要确保 “用于取消或到期的EVENT_TYPE_CD始终遵循特定的REG_ID PACKAGE_DESC的新订阅或UPSELL” 。这是因为幸运的是,“ NEW SUBSCRIPTION”和“ UPSELL”都比“ CANCELLATION”和“ EXPIRATION”的字母顺序都晚,所以按降序排列就可以对它们进行正确排序。
order by
event_type_cd desc