这是我对源数据的插入声明。
REM INSERTING into EXPORT_TABLE
SET DEFINE OFF;
Insert into EXPORT_TABLE values ('4VKMH','GUIDFREE','UPSELL',to_date('11-MAR-14 17:05:35','DD-MON-YY HH24:MI:SS'),to_date('11-MAR-14 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('11-JUN-14 23:59:00','DD-MON-YY HH24:MI:SS'),92,0);
Insert into EXPORT_TABLE values ('4VKMH','GUIDPAID','UPSELL',to_date('11-MAR-14 17:05:35','DD-MON-YY HH24:MI:SS'),to_date('12-JUN-14 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('10-MAR-15 23:59:00','DD-MON-YY HH24:MI:SS'),271,73.78);
Insert into EXPORT_TABLE values ('4VKMH','GUIDFREE','EXPIRATION',to_date('12-JUN-14 01:26:26','DD-MON-YY HH24:MI:SS'),to_date('11-MAR-14 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('11-JUN-14 23:59:00','DD-MON-YY HH24:MI:SS'),92,0);
Insert into EXPORT_TABLE values ('4VKMH','GUIDPAID','RENEWAL',to_date('11-MAR-15 01:23:01','DD-MON-YY HH24:MI:SS'),to_date('11-MAR-15 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('10-MAR-16 23:59:00','DD-MON-YY HH24:MI:SS'),365,99);
Insert into EXPORT_TABLE values ('4VKMH','GUIDPAID','CANCELLATION',to_date('11-MAR-15 03:11:09','DD-MON-YY HH24:MI:SS'),to_date('11-MAR-15 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('11-MAR-15 23:59:00','DD-MON-YY HH24:MI:SS'),0,-99);
Insert into EXPORT_TABLE values ('4VKMH','GUIDPAID','UPSELL',to_date('16-MAR-15 10:49:34','DD-MON-YY HH24:MI:SS'),to_date('16-MAR-15 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('10-MAR-16 23:59:00','DD-MON-YY HH24:MI:SS'),360,97.92);
Insert into EXPORT_TABLE values ('4VKMH','GUIDPAID','CANCELLATION',to_date('22-FEB-16 18:19:00','DD-MON-YY HH24:MI:SS'),to_date('16-MAR-15 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('22-FEB-16 23:59:00','DD-MON-YY HH24:MI:SS'),343,-4.61);
Insert into EXPORT_TABLE values ('4VKMH','GUIDPAID','NEW SUBSCRIPTION',to_date('23-FEB-16 13:08:05','DD-MON-YY HH24:MI:SS'),to_date('23-FEB-16 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('22-FEB-18 23:59:00','DD-MON-YY HH24:MI:SS'),730,178);
Insert into EXPORT_TABLE values ('4VKMH','GUIDPAID','CANCELLATION',to_date('23-FEB-16 15:16:44','DD-MON-YY HH24:MI:SS'),to_date('23-FEB-16 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('23-FEB-16 23:59:00','DD-MON-YY HH24:MI:SS'),0,-178);
Insert into EXPORT_TABLE values ('4VKMH','GUIDGWA','UPSELL',to_date('23-FEB-16 15:22:42','DD-MON-YY HH24:MI:SS'),to_date('23-FEB-16 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('22-MAR-16 23:59:00','DD-MON-YY HH24:MI:SS'),28,0);
Insert into EXPORT_TABLE values ('4VKMH','GUIDGWA','CANCELLATION',to_date('11-MAR-16 04:25:50','DD-MON-YY HH24:MI:SS'),to_date('23-FEB-16 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('11-MAR-16 23:59:00','DD-MON-YY HH24:MI:SS'),17,0);
Insert into EXPORT_TABLE values ('4VKMH','GUIDPAID','UPSELL',to_date('14-MAR-16 10:02:05','DD-MON-YY HH24:MI:SS'),to_date('14-MAR-16 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('13-APR-16 23:59:00','DD-MON-YY HH24:MI:SS'),30,8.41);
Insert into EXPORT_TABLE values ('4VKMH','GUIDPAID','UPSELL',to_date('11-APR-16 09:33:06','DD-MON-YY HH24:MI:SS'),to_date('14-APR-16 00:00:00','DD-MON-YY HH24:MI:SS'),to_date('13-MAR-17 23:59:00','DD-MON-YY HH24:MI:SS'),333,90.59);
我的源数据为
REG_ID | PRODUCT_CD | EVENT_TYPE | EVENT_DATE | TERM_START_DATE | TERM_END_DATE | DAYS | AMT
--------+------------+-----------------+--------------------+--------------------+--------------------+------+--------
4VKMH | GUIDFREE | UPSELL | 11-MAR-14 17:05:35 | 11-MAR-14 00:00:00 | 11-JUN-14 23:59:00 | 92 | 0
4VKMH | GUIDPAID | UPSELL | 11-MAR-14 17:05:35 | 12-JUN-14 00:00:00 | 10-MAR-15 23:59:00 | 271 | 73.78
4VKMH | GUIDFREE | EXPIRATION | 12-JUN-14 01:26:26 | 11-MAR-14 00:00:00 | 11-JUN-14 23:59:00 | 92 | 0
4VKMH | GUIDPAID | RENEWAL | 11-MAR-15 01:23:01 | 11-MAR-15 00:00:00 | 10-MAR-16 23:59:00 | 365 | 99 *
4VKMH | GUIDPAID | CANCELLATION | 11-MAR-15 03:11:09 | 11-MAR-15 00:00:00 | 11-MAR-15 23:59:00 | 0 | -99
4VKMH | GUIDPAID | UPSELL | 16-MAR-15 10:49:34 | 16-MAR-15 00:00:00 | 10-MAR-16 23:59:00 | 360 | 97.92
4VKMH | GUIDPAID | CANCELLATION | 22-FEB-16 18:19:00 | 16-MAR-15 00:00:00 | 22-FEB-16 23:59:00 | 343 | -4.61
4VKMH | GUIDPAID | NEW SUBSCRIPTION| 23-FEB-16 13:08:05 | 23-FEB-16 00:00:00 | 22-FEB-18 23:59:00 | 730 | 178
4VKMH | GUIDPAID | CANCELLATION | 23-FEB-16 15:16:44 | 23-FEB-16 00:00:00 | 23-FEB-16 23:59:00 | 0 | -178
4VKMH | GUIDGWA | UPSELL | 23-FEB-16 15:22:42 | 23-FEB-16 00:00:00 | 22-MAR-16 23:59:00 | 28 | 0
4VKMH | GUIDGWA | CANCELLATION | 11-MAR-16 04:25:50 | 23-FEB-16 00:00:00 | 11-MAR-16 23:59:00 | 17 | 0
4VKMH | GUIDPAID | UPSELL | 14-MAR-16 10:02:05 | 14-MAR-16 00:00:00 | 13-APR-16 23:59:00 | 30 | 8.41
4VKMH | GUIDPAID | UPSELL | 11-APR-16 09:33:06 | 14-APR-16 00:00:00 | 13-MAR-17 23:59:00 | 333 | 90.59
此数据已按REG_ID
,EVENT_DATE
和TERM_START_DATE
排序。
我正在尝试从中生成此输出:
REG_ID | PRODUCT_CD | EVENT_TYPE | EVENT_DATE | TERM_START_DATE | TERM_END_DATE | DAYS | AMT
--------+------------+-----------------+--------------------+--------------------+--------------------+------+--------
4VKMH | GUIDFREE | UPSELL | 11-MAR-14 17:05:35 | 11-MAR-14 00:00:00 | 11-JUN-14 23:59:00 | 92 | 0
4VKMH | GUIDPAID | UPSELL | 11-MAR-14 17:05:35 | 12-JUN-14 00:00:00 | 10-MAR-15 23:59:00 | 271 | 73.78
4VKMH | GUIDFREE | EXPIRATION | 12-JUN-14 01:26:26 | 11-MAR-14 00:00:00 | 11-JUN-14 23:59:00 | 92 | 0
4VKMH | GUIDPAID | UPSELL | 16-MAR-15 10:49:34 | 16-MAR-15 00:00:00 | 22-FEB-16 23:59:00 | 360 | 97.92
4VKMH | GUIDPAID | CANCELLATION | 22-FEB-16 18:19:00 | 16-MAR-15 00:00:00 | 22-FEB-16 23:59:00 | 343 | -4.61
4VKMH | GUIDGWA | UPSELL | 23-FEB-16 15:22:42 | 23-FEB-16 00:00:00 | 11-MAR-16 23:59:00 | 28 | 0
4VKMH | GUIDGWA | CANCELLATION | 11-MAR-16 04:25:50 | 23-FEB-16 00:00:00 | 11-MAR-16 23:59:00 | 17 | 0
4VKMH | GUIDPAID | UPSELL | 14-MAR-16 10:02:05 | 14-MAR-16 00:00:00 | 13-APR-16 23:59:00 | 30 | 8.41
4VKMH | GUIDPAID | UPSELL | 11-APR-16 09:33:06 | 14-APR-16 00:00:00 | 13-MAR-17 23:59:00 | 333 | 90.59
这是从原始数据中得出结果的逻辑:
对于包含EVENT_TYPE
'RENEWAL'
,'UPSELL'
或'NEW SUBSCRIPTION'
的每条记录 A :如果以下记录 B 有EVENT_TYPE
'CANCELLATION'
,然后:
EVENT_DATE
日期部分,则删除记录 A 和<结果强> B 。所以这就是消除记录4,5,8和9的原因; TERM_END_DATE
,则更新 A &#39; s {{ 1}}到 B 的那个。所以这就是为什么记录10有一个更新的TERM_END_DATE
我已尝试使用以下SQL处理我的第一个条件并遇到问题ORA-00933:SQL命令未正确结束
TERM_END_DATE
答案 0 :(得分:2)
您的查询出错的原因是,在定义子查询之前,您必须指明要从中选择的内容。因此,如果您使用select * from
作为前缀,那么它将是一个有效的查询。
请注意,您不必执行这些or
操作,因为您可以使用in
运算符缩短操作时间。
您还应该否定某些比较(因为您已经NOT
)并使用TRUNC
截断日期。
以下是我建议的查询:
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))
请注意,记录6的 term_end_date 也会被修改,因为规则2适用于它。
答案 1 :(得分:1)
让我先说明我没有在Oracle中测试这个,因为我没有方便的Oracle数据库。
我把它简化为单个连接,将性能与接受的答案进行比较可能很有用。
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