Reputation: 1373
Say I have objects with a created_at
attribute. I would like to have
a query that will result in the counts of created objects on a given date
(count_
), subtotal of objects up to that date (sub
), and the full
total of all objects (total_
):
date | count_ | sub | total_
------------+--------+-------+-------
2018-10-08 | 1 | 1 | 15
2018-10-11 | 2 | 3 | 15
2018-10-15 | 3 | 6 | 15
2018-10-23 | 4 | 10 | 15
2018-10-24 | 5 | 15 | 15
I managed to get count_
and total_
:
Obj.objects.annotate(
date=Trunc('created_at', 'day', output_field=DateField())
).values(
'date'
).annotate(
count_=Window(expression=Count('id'), partition_by=[F('date')]),
total_=Window(expression=Count('id'))
).distinct()
generating this SQL
:
SELECT DISTINCT DATE_TRUNC('day', "obj_obj"."created_at") AS "date",
COUNT("obj_obj"."id") OVER (PARTITION BY DATE_TRUNC('day', "obj_obj"."created_at")) AS "count_",
COUNT("obj_obj"."id") OVER () AS "total_"
FROM "obj_obj"
Upvotes: 2
Views: 254
Reputation: 23756
You need the cumulative window function. This can be achieved by adding an ORDER BY
clause. If this exists, the COUNT()
will be cumulative as you expect. If it doesn't exist, the COUNT will be taken over the whole frame.
count(created_at) OVER (ORDER BY created_at) as subtotal
The query
SELECT DISTINCT
created_at,
count(created_at) OVER (PARTITION BY created_at) as count_,
count(created_at) OVER (ORDER BY created_at) as subtotal_,
count(created_at) OVER () as total_
FROM
dates
So although I am not really into Django I believe you need a line like:
subtotal_=Window(expression=Count('id'), order_by=[F('date')]),
Upvotes: 2