Вы можете явно указать, что добавляете дни, используя тип интервала;
LEFT JOIN CONTRACTS C1
ON (C.CUSTOMER_ID=C1.CUSTOMER_ID AND C.VALID_TO + INTERVAL '1' DAY=C1.VALID_FROM)
или более просто используйте арифметику даты , просто удалив слово '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;
Оба получают одинаковые результаты с вашими данными выборки.
db <> fiddle demo для всех четырех запросов. .