I am looking for assistance to get a running sum of the difference between two dates that are on separate rows.
Table looks like:
client_id | name | autopay_status | contract_id | start_date | end_date |
---|---|---|---|---|---|
1 | Contract 1 | Inactive | 1111 | "2019-08-30" | "2020-02-29" |
1 | Contract 1 | Inactive | 1112 | "2020-02-29" | "2020-08-29" |
1 | Contract 1 | Active | 1113 | "2020-08-29" | "2021-02-28" |
2 | Contract 2 | Inactive | 2221 | "2019-08-30" | "2020-02-29" |
2 | Contract 2 | Inactive | 2222 | "2020-02-29" | "2020-08-29" |
2 | Contract 2 | Active | 2223 | "2020-08-29" | "2021-02-28" |
3 | Contract 3 | Inactive | 3331 | "2019-08-30" | "2020-02-29" |
3 | Contract 3 | Inactive | 3332 | "2020-03-29" | "2020-09-29" |
3 | Contract 3 | Inactive | 3333 | "2020-09-29" | "2021-03-28" |
3 | Contract 3 | Active | 3334 | "2021-03-28" | "2021-09-28" |
I have a query that looks at the previous end_date and if it is within one day then that is a continuing contract.
SELECT
case when
(start_date - coalesce(lag(end_date) over (partition by client_id order by end_date), end_date)::date)::int <= 1 then true
else false
end as continous_contract,
end_date - start_date as contract_days,
client_id,
contract_id,
autopay_status,
start_date,
end_date
FROM
client_contracts
ORDER BY
client_id, start_date
This adds two extra alias columns.
continuous_contract | contract_days | client_id | name | autopay_status | contract_id | start_date | end_date |
---|---|---|---|---|---|---|---|
true | 183 | 3 | Contract 3 | Inactive | 3331 | "2019-08-30" | "2020-02-29" |
false | 184 | 3 | Contract 3 | Inactive | 3332 | "2020-03-29" | "2020-09-29" |
true | 183 | 3 | Contract 3 | Inactive | 3333 | "2020-09-29" | "2021-03-28" |
true | 182 | 3 | Contract 3 | Active | 3334 | "2021-03-28" | "2021-09-28" |
My goal here is to sum up the days a client has had a continuous contract so table would look similar to below for the above example:
sum_days | continuous_contract | contract_days | client_id |
---|---|---|---|
183 | true | 183 | 3 |
184 | false | 184 | 3 |
367 | true | 183 | 3 |
549 | true | 182 | 3 |
733 | true | 184 | 3 |
181 | false | 181 | 3 |
I have put together the below query, but it only sums up the previous two values.
SELECT
*
FROM
(
SELECT
*,
case
when cc.continuous_contract = true then
cc.contract_days + coalesce(lag(cc.contract_days) over (partition by cc.client_id), 1)
else cc.contract_days
end as added_contract_days
FROM (
SELECT
case when
(start_date - coalesce(lag(end_date) over (partition by client_id order by end_date), end_date)::date)::int <= 1 then true
else false
end as continuous_contract,
end_date - start_date as contract_days,
client_id,
contract_id,
autopay_status,
start_date,
end_date
FROM
client_contracts
) as cc
) as ccc
I am happy to change anything around to make this work.
Fiddle for assisting in seeing data and structure: Fiddle