Reputation: 541
For each customer I want to discard all the contracts with a continuation (one contract is closed and another one opens the following day - for the same customer)
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
I have to change C.VALID_TO + 1 DAY, what is the right syntax in Oracle?
Upvotes: 0
Views: 52
Reputation: 191435
You can either explicitly say you're adding days by using an interval type;
LEFT JOIN CONTRACTS C1
ON (C.CUSTOMER_ID=C1.CUSTOMER_ID AND C.VALID_TO + INTERVAL '1' DAY=C1.VALID_FROM)
or more simply use date arithmetic by just removing the word 'DAY' from your query:
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
As a bonus, two alternative approaches; rather than using a left join, use 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;
or use an inline view and an analytic lead()
call so you only have to hit the table once:
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;
Both get the same result with your sample data.
db<>fiddle demo of all four queries..
Upvotes: 2