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