对于每个客户,我都希望放弃所有续签的合同(一个合同已关闭,第二天又打开了-同一客户)
CONTRACTS
- ID (PK INTEGER)
- CUSTOMER_ID (FK INTEGER NOT NULL)
- VALID_FROM (DATE NOT NULL)
- VALID_TO (DATE NULLABLE)
ID|CUSTOMER_ID|VALID_FROM|VALID_TO
1|1|2018-01-01|2018-07-31
2|1|2018-11-01|NULL
3|2|2018-03-01|2018-04-30
4|2|2018-05-01|2018-11-30
5|3|2018-06-01|NULL
ID|CUSTOMER_ID|VALID_FROM|VALID_TO
1|1|2018-01-01|2018-07-31
2|1|2018-11-01|NULL
4|2|2018-05-01|2018-11-30
5|3|2018-06-01|NULL
SELECT
C.*
FROM CONTRACTS C
LEFT JOIN CONTRACTS C1 ON (C.CUSTOMER_ID=C1.CUSTOMER_ID AND *C.VALID_TO + 1 DAY*=C1.VALID_FROM)
WHERE C1.ID IS NULL
我必须更改 C.VALID_TO + 1天,Oracle中正确的语法是什么?
答案 0 :(得分:2)
您可以使用间隔类型明确表示要添加天数;
LEFT JOIN CONTRACTS C1
ON (C.CUSTOMER_ID=C1.CUSTOMER_ID AND C.VALID_TO + INTERVAL '1' DAY=C1.VALID_FROM)
或更简单地使用date arithmetic,只需从查询中删除单词“ DAY”即可。
SELECT
C.*
FROM CONTRACTS C
LEFT JOIN CONTRACTS C1 ON (C.CUSTOMER_ID=C1.CUSTOMER_ID AND C.VALID_TO + 1=C1.VALID_FROM)
WHERE C1.ID IS NULL
ORDER BY C.CUSTOMER_ID, C.VALID_FROM;
ID CUSTOMER_ID VALID_FROM VALID_TO
---------- ----------- ---------- ----------
1 1 2018-01-01 2018-07-31
2 1 2018-11-01
4 2 2018-05-01 2018-11-30
5 3 2018-06-01
作为奖励,有两种替代方法;与其使用左联接,不如使用not exists
:
SELECT
C.*
FROM CONTRACTS C
WHERE NOT EXISTS (
SELECT *
FROM CONTRACTS C1
WHERE C.CUSTOMER_ID=C1.CUSTOMER_ID AND C.VALID_TO + 1=C1.VALID_FROM
)
ORDER BY C.CUSTOMER_ID, C.VALID_FROM;
或使用内联视图和分析型lead()
调用,因此您只需要点击一次表即可:
SELECT ID, CUSTOMER_ID, VALID_FROM, VALID_TO
FROM (
SELECT
C.*,
LEAD(VALID_FROM) OVER (PARTITION BY CUSTOMER_ID ORDER BY VALID_FROM) AS LEAD_VALID_FROM
FROM CONTRACTS C
)
WHERE LEAD_VALID_FROM IS NULL OR VALID_TO + 1 != LEAD_VALID_FROM
ORDER BY CUSTOMER_ID, VALID_FROM;
两者与您的样本数据都得到相同的结果。