Group by query in Django - django

I am still in the same problem. I hope you cooperate in the solution. I want to get the result of this query in Django.
SELECT city_name, MAX(total_places) total_places
FROM(SELECT city city_name, COUNT(city) total_places
FROM Places
GROUP BY 1) t1
GROUP BY 1;

If I look at this answer, it should be something like:
Places.objects.annotate(total=COUNT('city')).latest('total')

Related

How to get all users of a group in Django?

I want to get a list of all users who are within a Django Group. For example:
User.objects.filter(group='Staff')
I cannot find how to do this query anywhere in the docs.
The following query solved my problem.
User.objects.filter(groups__name='Staff')
Thanks to #SardorbekImomaliev for figuring it out.
This query allows you to find users by group id rather than by group name:
group = Group.objects.get(id=group_id)
users = group.user_set.all()
Here's a query that lets you search by group name:
users = User.objects.filter(groups_name='group_name')

Nested SQL queries in Django

I've got a working SQL query that I'm trying to write in Django (without resorting to RAW) and was hoping you might be able to help.
Broadly, I'm looking to next two queries - the first calculates a COUNT, and then I'm looking to calculate an AVERAGE of the COUNTS. (this'll give you the average number of items on a ticket, per location)
The SQL that works is:
SELECT location_name, Avg(subq.num_tickets) FROM (
SELECT Count(ticketitem.id) AS num_tickets, location.name AS location_name
FROM ticketitem
JOIN ticket ON ticket.id = ticketitem.ticket_id
JOIN location ON location.id = ticket.location_id
JOIN location ON location.id = location.app_location_id
GROUP BY ticket_id, location.name) AS subq
GROUP BY subq.location_name;
For my Django code, I'm trying something like this:
# Get the first count
qs = TicketItem.objects.filter(<my complicated filter>).\
values('ticket__location__app_location__name','posticket').\
annotate(num_tickets=Count('id'))
# now get the average of the count
qs2 = qs.values('ticket__location__app_location__name').\
annotate(Avg('num_tickets')).\
order_by('location__app_location__name')
but that fails because num_tickets doesn't exist ... Anyway - suspect I'm being slow. Would love someone to enlighten me!
Check out the section on aggregating annotations from the Django docs. Their example takes an average of a count.
I was playing around with this a bit in a manage.py shell, and I think the django ORM might not be able to do that kind of annotation. Honestly you're probably going to have to resort to doing a raw query or bind in something like https://github.com/Deepwalker/aldjemy which would let you do that via SQLAlchemy.
When I playing with this I tried
(my_model.objects.filter(...)
.values('parent_id', 'parent__name', 'thing')
.annotate(Count('thing'))
.values('name', 'thing__count')
.annotate(Avg('thing__count')))
Which gave a lovely traceback about FieldError: Cannot compute Avg('thing__count'): 'thing__count' is an aggregate, which makes sense since I doubt the ORM is trying to convert that first group by to a nested query.

Annotate in one model Django

See my model
https://github.com/rg3915/morris/blob/master/myproject/core/models.py
How to return percent 'uf' of total?
Example:
'uf','quant'
'AM',8
'SP',9
'RJ',4
I try
p=Person.objects.values('uf').annotate(quant=Count('uf', distinct=True)).values_list('uf','quant')
print(p.query)
but return
SELECT "core_person"."uf", COUNT(DISTINCT "core_person"."uf") AS "quant" FROM "core_person" GROUP BY "core_person"."uf", "core_person"."first_name" ORDER BY "core_person"."first_name" ASC
and i need
SELECT "core_person"."uf", COUNT(DISTINCT "core_person"."uf") AS "quant" FROM "core_person" GROUP BY "core_person"."uf" ORDER BY "core_person"."uf" ASC
From your example, I'm going to assume that you are looking to retrieve a list of states and the total number of people that belong to that state.
You were pretty close in your attempt, however you were lacking an order_by() that would have let you choose the order field.
As such your query should look like this:
Person.objects.values('uf').annotate(quant=Count('uf')).order_by('uf').values_list('uf','quant')
I hope you'll notice that I have also removed the distinct=True argument from the Count function, as we want to be able to group all of the similar results.

How to use Group by clause in django with the filter query

I went through a lot of links and sites , but i can't find the solution for my problem anywhere. So at last i came here .
My problem is that, I want to use the group by clause with the filter query.
i have found this
How to query as GROUP BY in django?
for objects.all() . But could not find anything for objects.filter()
Here is my query
query =Kicthen.objects.filter( cabinets='1').query
query.group_by = ['style_id']
results = QuerySet(query=query, model=Kicthen)
But its return nothing.
I don't want to use any annotate and distinct with it
Use can use raw to make group by
http://doughellmann.com/2007/12/using-raw-sql-in-django.html

Get distinct values of Queryset by field

I've got this model:
class Visit(models.Model):
timestamp = models.DateTimeField(editable=False)
ip_address = models.IPAddressField(editable=False)
If a user visits multiple times in one day, how can I filter for unique rows based on the ip field? (I want the unique visits for today)
today = datetime.datetime.today()
yesterday = datetime.datetime.today() - datetime.timedelta(days=1)
visits = Visit.objects.filter(timestamp__range=(yesterday, today)) #.something?
EDIT:
I see that I can use:
Visit.objects.filter(timestamp__range=(yesterday, today)).values('ip_address')
to get a ValuesQuerySet of just the ip fields. Now my QuerySet looks like this:
[{'ip_address': u'127.0.0.1'}, {'ip_address': u'127.0.0.1'}, {'ip_address':
u'127.0.0.1'}, {'ip_address': u'127.0.0.1'}, {'ip_address': u'127.0.0.1'}]
How do I filter this for uniqueness without evaluating the QuerySet and taking the db hit?
# Hope it's something like this...
values.distinct().count()
What you want is:
Visit.objects.filter(stuff).values("ip_address").annotate(n=models.Count("pk"))
What this does is get all ip_addresses and then it gets the count of primary keys (aka number of rows) for each ip address.
With Alex Answer I also have the n:1 for each item. Even with a distinct() clause.
It's weird because this is returning the good numbers of items :
Visit.objects.filter(stuff).values("ip_address").distinct().count()
But when I iterate over "Visit.objects.filter(stuff).values("ip_address").distinct()" I got much more items and some duplicates...
EDIT :
The filter clause was causing me troubles. I was filtering with another table field and a SQL JOIN was made that was breaking the distinct stuff.
I used this hint to see the query that was really used :
q=Visit.objects.filter(myothertable__field=x).values("ip_address").distinct().count()
print q.query
I then reverted the class on witch I was making the query and the filter to have a join that doesn't rely on any "Visit" id.
hope this helps
The question is different from what the title suggests. If you want set-like behavior from the database, you need something like this.
x = Visit.objects.all().values_list('ip_address', flat=True).distinct()
It should give you something like this for x.
[1.2.3.4, 2.3.4.5, ...]
Where
len(x) == len(set(x))
Returns True