Reputation: 2154
I have a data table of donation_dates by donor_id. I would like to return the number of continuous years of donations.
WITH DONATIONS AS
(
SELECT 123 AS donor_account_id, DATE '2022-10-10' AS donation_date
UNION ALL
SELECT 123 AS donor_account_id, DATE '2021-10-10' AS donation_date
UNION ALL
SELECT 123 AS donor_account_id, DATE '2020-09-10' AS donation_date
UNION ALL
SELECT 123 AS donor_account_id, DATE '2020-10-10' AS donation_date
UNION ALL
SELECT 123 AS donor_account_id, DATE '2019-10-10' AS donation_date
UNION ALL
SELECT 123 AS donor_account_id, DATE '2017-10-10' AS donation_date
UNION ALL -- shouldn't count
SELECT 456 AS donor_account_id, DATE '2021-10-10' AS donation_date
UNION ALL
SELECT 456 AS donor_account_id, DATE '2020-10-10' AS donation_date
UNION ALL
SELECT 456 AS donor_account_id, DATE '2020-01-10' AS donation_date
UNION ALL
SELECT 456 AS donor_account_id, DATE '2019-10-10' AS donation_date
UNION ALL
SELECT 456 AS donor_account_id, DATE '2019-01-10' AS donation_date
UNION ALL
SELECT 789 AS donor_account_id, DATE '2020-10-10' AS donation_date
UNION ALL -- shouldn't count
SELECT 789 AS donor_account_id, DATE '2019-10-10' AS donation_date
-- shouldn't count
)
I was able to get sequential years if entry exists for current year (as in id 123). However, since current year is not done, I should also include donors from last year since they could still donate by end of year (as in id 456).
Here is my code:
SELECT
CY.ID AS id, COUNT(CY.YEAR) AS cont_years
FROM
(SELECT
DY.ID, DY.YEAR,
RANK() OVER (PARTITION BY DY.ID ORDER BY DY.YEAR DESC) AS CT,
(YEAR + RANK() OVER (PARTITION BY DY.ID ORDER BY DY.YEAR DESC)) AS FLAG
FROM
(SELECT DISTINCT
D.donor_account_id ID,
EXTRACT(YEAR FROM D.donation_date) YEAR
FROM
DONATIONS D
GROUP BY
1, 2) DY
ORDER BY
1, 2 DESC) CY
WHERE
CY.FLAG = EXTRACT(YEAR FROM CURRENT_DATE) + 1
GROUP BY
1
These are the expected correct results from the table above, but my code is unable to query id 456:
Upvotes: 0
Views: 98
Reputation: 12264
You might consider below query.
SELECT DISTINCT donor_account_id, COUNT(DISTINCT donation_year) OVER w1 AS cont_years FROM (
SELECT *, donation_year - DENSE_RANK() OVER w0 AS part
FROM (SELECT *, EXTRACT(YEAR FROM donation_date) donation_year FROM DONATIONS)
WINDOW w0 AS (PARTITION BY donor_account_id ORDER BY donation_year)
) QUALIFY COUNTIF(donation_year IN (2021, 2022)) OVER w1 > 0
WINDOW w1 AS (PARTITION BY donor_account_id, part);
+------------------+------------+
| donor_account_id | cont_years |
+------------------+------------+
| 123 | 4 |
| 456 | 3 |
+------------------+------------+
Upvotes: 1