{{{
class Xyz(models.Model):
a = models.IntegerField()
b = models.IntegerField()
}}}
If I want to find percent ratio of sum of all `a` and sum of all `b`, I
can write:
{{{
Xyz.objects.aggregate(ratio_percent=Sum('a')/Sum('b')*100)
}}}
This type of functionality has been implemented in this commit
https://github.com/debanshuk/django/commit/722f7a4a17870fe1ffb6c207153d1fca6388a401
More operations (like pow) can also be added.
--
Ticket URL: <https://code.djangoproject.com/ticket/20930>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0
Comment:
Also added pull request https://github.com/django/django/pull/1484
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:1>
* keywords: => aggregate, annotate
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:2>
Comment (by wim@…):
Hi debanshuk,
Wouldn't it be possible to make the same calculation outside of the
aggregate? That seems cleaner to me.
Wim
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:3>
Comment (by debanshuk):
Hi Wim,
In the example given in the description, it would. And I guess in case of
aggregates it would always be possible to make the calculations out side
aggregate.
But, '''in case of annotate it would not'''. Well, it would certainly be
possible, but wouldn’t be cleaner, as one would have to do the
calculations for each element in resultant query-set.
Eg. Let modified `Xyz` be:
{{{
class Xyz(models.Model):
user = models.ForeignKey(User)
a = models.IntegerField()
b = models.IntegerField()
}}}
Now if I want to find find percent ratio of sum of all `a` and sum of all
`b` of a `user`, for each `user`. I may write:
{{{
Xyz.objects.values('user').annotate(ratio_percent=Sum('a')/Sum('b')*100)
}}}
Currently, to do this (without writing raw SQL), one would have to do
something like:
{{{
result = Xyz.objects.values('user').annotate(total_a=Sum('a'),
total_b=Sum('b'))
final_result = [{'user': r['user'], 'ratio_percent':
r['total_a']/r['total_b']*100} for r in result]
}}}
'''Also''', If someone want to aggregate over annotation results, like in
the example if I want to find maximum of the ratio_percentage, I may do:
{{{
Xyz.objects.values('user').annotate(ratio_percent=Sum('a')/Sum('b')*100).aggregate(Max('ratio_percent'))
}}}
Currently, I would have to do:
{{{
result = Xyz.objects.values('user').annotate(total_a=Sum('a'),
total_b=Sum('b'))
final_result = max(r['total_a']/r['total_b']*100 for r in result)
}}}
'''In the second one, max calculation in done in python. In the first one
it is done in SQL itself.'''
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:4>
Comment (by timo):
Duplicate of #14030?
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:5>
Comment (by debanshuk):
Well...not exactly duplicate, as #14030 is for something like this:
{{{
Xyz.objects.aggregate(Sum(F('a')/F('b')*100))
}}}
but I guess #14030 can be extended to implement functionality of this
ticket. In case of `annotate` something like this can be done:
{{{
Xyz.objects.values('user').annotate(total_a=Sum('a'),
total_b=Sum('b')).values(F('total_a')/F('total_b')*100)
}}}
**But**, in case of `aggregate` this wont work as `aggregate` returns
`dict` (not `QuerySet`). So, I guess some changes are required for
`aggregate`.
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:6>
* needs_better_patch: 0 => 1
* needs_docs: 0 => 1
* needs_tests: 0 => 1
* stage: Unreviewed => Accepted
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:7>
* status: new => assigned
* owner: nobody => debanshuk
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:8>
Comment (by debanshuk):
Added pull request https://github.com/django/django/pull/1510. Fixed code
and added tests and docs.
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:9>
Comment (by debanshuk):
Did amendment in the commit. Updated some conditions in test-cases to make
them more reliable.
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:10>
* owner: debanshuk =>
* status: assigned => new
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:11>
* cc: jorgecarleitao@… (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:12>
Comment (by jarshwah):
FYI - the implementation of #14030 satisfies this ticket.
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:13>
* status: new => closed
* resolution: => duplicate
--
Ticket URL: <https://code.djangoproject.com/ticket/20930#comment:14>