I’m having a table similar to this:
| first | last | date | pos | 
|---|---|---|---|
| john | doe | 18-03-2021 | |
| harris | potter | 10-06-2021 | |
| john | doe | 10-05-2021 | |
| harris | potter | 14-06-2021 | |
| jessica | potter | 14-06-2021 | |
| kermit | foster | 
The use case is as follow:
- The pos column correspond to a positive covid test
 - The date column correspond to the vaccination date
 
To be elligible for a covid certificate, some one must either:
- Been tested positive and have got 1 vaccine
 - Have receive 2 vaccine
 
I’m trying to write a query that return me: totalDose, totalRequieredDose
For exemple:
- If he has tested positive, the totalRequiredDose is 1 and if he has got 1 vaccine, he is elligible. As such, for Harry Potter, totalDoses=1 and totalRequieredDoses=1 and is elligible
 - If he has not been tested positive, the totalRequiredDose is 2 and if he has got 2 vaccines, he is elligible. As such, for John Doe, totalDoses=2 and totalRequieredDoses=2 and is elligible
 
| first | last | totalDoses | totalRequieredDoses | 
|---|---|---|---|
| john | doe | 2 | 2 | 
| harris | potter | 1 | 1 | 
| jessica | potter | 1 | 2 | 
| kermit | foster | 0 | 2 | 
As Jessica Potter have a vaccine and no pos date, she must have 2 vaccines. So the value 1/2 And Kermit foster have no pos value, he is 0/2 Etc.
I’m scratching my head to write a query (or pl/sql) that could return me such table.
Could someone give me some hints ?
Advertisement
Answer
We can aggregate by first and last name.  The total doses is simply the count of non NULL vaccination dates.  For the total required number of doses, we can start with a value of 2.  This value can then be offset by 1 assuming there exists a non NULL date for the pos column, indicating that a given person tested positive at some point.
SELECT
    first,
    last,
    COUNT(date) AS totalDoses,
    2 - (COUNT(*) FILTER (WHERE pos IS NOT NULL) > 0)::int AS totalRequieredDoses
FROM yourTable
GROUP BY
    first,
    last
ORDER BY
    COUNT(date) DESC,
    first,
    last;
