This is my insert Statements for the Source data.
REM INSERTING into EXPORT_TABLE
SET DEFINE OFF;
Insert into EXPORT_TABLE values (\'4VKMH\',\'GUIDFREE
The reason why you got an error on your query is that before the sub-query is defined, you must indicate what you want to select from it. So if you had prefixed that with select * from
it would have been a valid query.
Note that you don't have to do those or
operations, as you can do that shorter with an in
operator.
You should also negate some comparisons (as you already have NOT
) and truncate dates with TRUNC
.
Here is the query I would suggest:
SELECT TEMP.REG_ID,
TEMP.EVENT_TYPE,
TEMP.EVENT_DATE,
TEMP.PRODUCT_CD,
TEMP.TERM_START_DATE,
CASE WHEN TEMP.EVENT_TYPE IN ('NEW SUBSCRIPTION', 'RENEWAL', 'UPSELL')
AND TEMP.NEXT_EVENT_TYPE = 'CANCELLATION' THEN
LEAST(TEMP.TERM_END_DATE, TEMP.NEXT_TERM_END_DATE)
ELSE TEMP.TERM_END_DATE
END AS TERM_END_DATE,
TEMP.DAYS,
TEMP.AMT
FROM (SELECT REG_ID,
EVENT_TYPE,
EVENT_DATE,
PRODUCT_CD,
TERM_START_DATE,
TERM_END_DATE,
DAYS,
AMT,
LAG(EVENT_TYPE, 1, '-') over (
PARTITION BY REG_ID, PRODUCT_CD
ORDER BY EVENT_DATE, TERM_START_DATE) as PREV_EVENT_TYPE,
LAG(EVENT_DATE, 1) over (
PARTITION BY REG_ID, PRODUCT_CD
ORDER BY EVENT_DATE, TERM_START_DATE) as PREV_EVENT_DATE,
LEAD(EVENT_TYPE, 1, '-') over (
PARTITION BY REG_ID, PRODUCT_CD
ORDER BY EVENT_DATE, TERM_START_DATE) as NEXT_EVENT_TYPE,
LEAD(EVENT_DATE, 1) over (
PARTITION BY REG_ID, PRODUCT_CD
ORDER BY EVENT_DATE, TERM_START_DATE) as NEXT_EVENT_DATE,
LEAD(TERM_END_DATE, 1) over (
PARTITION BY REG_ID, PRODUCT_CD
ORDER BY EVENT_DATE, TERM_START_DATE) as NEXT_TERM_END_DATE
FROM export_table) TEMP
WHERE NOT (TEMP.EVENT_TYPE = 'CANCELLATION'
AND TEMP.PREV_EVENT_TYPE IN ('NEW SUBSCRIPTION', 'RENEWAL', 'UPSELL')
AND TRUNC(TEMP.EVENT_DATE) = TRUNC(TEMP.PREV_EVENT_DATE))
AND NOT (TEMP.NEXT_EVENT_TYPE = 'CANCELLATION'
AND TEMP.EVENT_TYPE IN ('NEW SUBSCRIPTION', 'RENEWAL', 'UPSELL')
AND TRUNC(TEMP.NEXT_EVENT_DATE) = TRUNC(TEMP.EVENT_DATE))
Note that the term_end_date of record 6 is also modified, as rule 2 is applicable to it.
Let me state up front that I didn't test this in Oracle as I don't have an Oracle database handy.
I pared it down to a single join, it may be useful to compare performance with the accepted answer.
select
e1.reg_id,
e1.product_cd,
e1.event_type,
e1.event_date,
e1.term_start_date,
case e1.event_type when 'CANCELLATION' then e1.term_end_date else coalesce(e2.term_end_date, e1.term_end_date) end as term_end_date,
e1.days,
e1.amt
from event e1
left outer join event e2 on
e1.reg_id = e2.reg_id and
e1.product_cd = e2.product_cd and
e1.term_start_date = e2.term_start_date and
(e1.event_type = 'CANCELLATION' or e2.event_type = 'CANCELLATION') and
e1.event_date <> e2.event_date
where trunc(e1.event_date) <> trunc(e2.event_date) or e2.reg_id is null