I have a table like this:
-----------------
id | date
-----------------
1 | 2023-10-07
2 | 2023-10-08
3 | 2023-10-14
and I want to get the record count up to the current record where the date is less than Sunday of the current record. So I want the output to look like this:
---------------------
week_number | count
---------------------
2 | 2
3 | 3
I tried different approaches, but the result is a counter for entries within the week. It’s as if he doesn’t look at all records before the current one, but only at those that are in the same week.
WITH weekly AS (
SELECT
get_week_number(date::DATE) AS week_number,
COUNT(*) AS count
FROM
inventory
WHERE
date <= date_trunc('week', date)::date + INTERVAL '6 days'
GROUP BY
week_number
)
SELECT
week_number, count
FROM
inventory
JOIN weekly ON get_week_number(date::DATE) = weekly.week_number
WHERE
date <= date_trunc('week', date)::date + INTERVAL '6 days'
GROUP BY
week_number, count
ORDER BY
week_number;
2
Answers
You’re probably looking for window functions. Demo at db<>fiddle
Default window frame clause is
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
, meaningcount()over()
is going to get the record count up to the current record the way you wanted.This computes
I assume by "Sunday of the current record" you mean weeks starting on Sunday. ISO weeks start on Monday.
date_trunc()
truncates weeks accordingly. Usedate_bin()
to "truncate" to Sunday. See:Add a day to your date before extracting the week number to fix the same off-by-1 error. (There may be corner-case issues around the turn of the year.)
To get the count of rows with a "date is less than Sunday of the current record", you have to stop the count at "last week".
RANGE BETWEEN UNBOUNDED PRECEDING AND '1 day' PRECEDING
achieves that, after reducing every date to the Sunday of the week.Details in the manual about window functions.
To aggregate per week:
Note that a week number without year results in confusing or wrong aggregations quickly. So I based counts on full dates and display the year additionally. (No off-by-1 there.)
fiddle