I have 2 tables on my db:
1- scheduled services
2- services realized.
On 2nd table, I have the value $ received for the service and the date the service was realized.
On 1st table, I only have the scheduled dates without values.
The point is:
Sometimes the scheduled service can’t be done, and it have to be re-scheduled, so the realized date can be different than the scheduled date.
But, even when the service wasn’t realized, I want to know how much $ was scheduled every day.
I’ve created a view (vw_test) that looks like:
vw_test:
SELECT
t1.date,
t1.service,
t2.value
FROM
scheduled AS t1
LEFT JOIN
realized AS t2
ON CONCAT(t1.date, t1.service) = CONCAT(t2.date, t2.service)
ORDER BY
t1.service ASC,
t2.date ASC
vw_test:
date | service | value |
---|---|---|
2023-04-01 | A | Null |
2023-04-02 | A | Null |
2023-04-03 | A | Null |
2023-04-04 | A | Null |
2023-04-05 | A | Null |
2023-04-06 | A | Null |
2023-04-07 | A | 150.80 |
2023-04-08 | A | Null |
2023-04-09 | A | Null |
2023-04-10 | A | Null |
2023-04-01 | B | Null |
2023-04-02 | B | Null |
2023-04-03 | B | 247.17 |
2023-04-04 | B | Null |
2023-04-05 | B | Null |
2023-04-06 | B | Null |
2023-04-07 | B | Null |
2023-04-08 | B | 75.12 |
2023-04-09 | B | Null |
2023-04-10 | B | Null |
I’m trying to fill the Null values with the next Non-Null value and keep Null for values after the Non-Null value for every service, like the table below:
date | service | value |
---|---|---|
2023-04-01 | A | 150.80 |
2023-04-02 | A | 150.80 |
2023-04-03 | A | 150.80 |
2023-04-04 | A | 150.80 |
2023-04-05 | A | 150.80 |
2023-04-06 | A | 150.80 |
2023-04-07 | A | 150.80 |
2023-04-08 | A | Null |
2023-04-09 | A | Null |
2023-04-10 | A | Null |
2023-04-01 | B | 247.17 |
2023-04-02 | B | 247.17 |
2023-04-03 | B | 247.17 |
2023-04-04 | B | 75.12 |
2023-04-05 | B | 75.12 |
2023-04-06 | B | 75.12 |
2023-04-07 | B | 75.12 |
2023-04-08 | B | 75.12 |
2023-04-09 | B | Null |
2023-04-10 | B | Null |
Is that possible to achieve with PostgreSQL?
I’ve tried ARRAY_AGG like mentioned in text
and JSONB_AGG text
but the result is the same as the vw_test.
Thanks for the help
2
Answers
I would use a gaps-and-islands approach for this.
I know that
vw_test
is a view for you. I simplified my example by making it a table:I left the intermediate columns in there to illustrate how the query works.
Working example.
Here is one way to do it with window functions:
The idea is to build groups of rows that contain a single rows with a non-
null
value, optionnaly preceded by any number of rows withnull
values: that’s what the windowcount
in the subquery does.All that is then left to do is to re-assign the (only) non-
null
value of the group to each row of the group.fiddle