django: getting aggregation values through OneToOne relation - django

I'm working on a QA system in django, which includes data tables of Question, Answer and Answer_statistics. One Question can have multiple Answers, an Answer has an Answer_statistics. Answer_statistics contain values like votes count, comments count of each answer. Now I'm trying to get the sum of a column in answer_statistics filtered by the question the answers are attached to. For example, get the total vote count of all the answers to a certain question. It should be something like this:
a_question.answer__answer_statistics_set.aggregate(Sum('comment_count'))
Feels like there should be some kind of easy solutions, but couldn't find one by now. Could someone please give a hint? Thanks!

You follow the relationship inside the aggregate call, not in the object lookup. Something like:
a_question.aggregate(Sum('answer__answer_statistics__comment_count'))

Related

How does distinct parameter work with the Count method in annotate?

I got a problem with annotate method when I was using the Count method to count multiple columns that come from the database which have a relationship with one of the tables.
Let me give you a quick example:
match_session_instance = MatchSessionInstance.objects.filter(match_session=match_session, status="main")
match_instances = MatchSessionInstance.objects.filter(match_session=match_session)
action_counts = match_instances.values(player_number=F("player_pk__number"), player_name=F("player_pk__player"))\
.annotate(pass_count=Count("live_match_pass__id", distinct=True),
corner_count=Count("live_match_corner__id", distinct=True))
In the meantime, I'm not facing any problems - I caught my issue and I addressed it but that is the problem now.
I don't know how could "disticnt=True" parameter helps me to fix that problem!
I googled a bit and found this source that has helped me:
Count on multiple fields in Django querysets
I know what does distinct as a method in ORM but actually, I get no idea how it works in that format special when I used columns that never have duplicated data.
How can I understand this?

POWERBI: take while table when there is no available relation

I have a slight issue with my tables in POWERBI. In short, I have a missing link in one of my relations. As a result, instead of returning NOTHING which is logical and actually what I would like, it returns EVERYTHING.
A bit more details, I have the multiple tables with relations between them. The problem is that I have a few task_group pointing toward shipments that do not exist. In my visualization, I am trying to access data (a count of the number of Packages linked to a shipment) that is linked to a shipment. The logical thing for me would be that "If there is no shipment fitting the number that is given in the shipment table, then you cannot count the number of packages linked to that shipment".
But PowerBI beg to differ. His idea is "If I cannot find a shipment to link to package, i'm going to take every single package regardless of shipment". As a result, a group of task that do not have any package end up showing as having all the packages instead. How can I tell powerbi to return nothing if he doesn't find anything instead of returning everything?
Image of my relationships
I think Power BI behaves slightly unintuitively where there are nulls on one side of a join.
Have you tried filtering to only include where shipment_id is not blank?
If the problem is you having NULLs in one side of the relationship, the best way to tackle this would be to replace the NULLs with something else. Now, you can do it in two ways:
Edit the Shipment number NULLs to something else in the Power query while importing (Some number which is not likely to be an actual shipment, maybe 0)
Create a calculated field in DAX replacing the blanks/NULLs and use that in the relationship instead
But I think you may have NULLs in both the sides of the relationship. That is the only explanation I can think of, why Power BI is behaving this way. Either way, the above solutions should fix it.

Django Query, Distinct and Order_By combination not working

There are similar questions here but I haven't been able to find one that helps me.
I have two models, Chat and Post
there are multiple Chats, and each chat has multiple posts attached to it.
I'm trying to get the latest post for each chat.
Post.objects.order_by('-id').distinct('Chat')
Filter the posts by ID (so the newest post is first), and then grab the distinct ones based on the Chats.
but since order_by and distinct don't match I'm getting the error:
SELECT DISTINCT ON expressions must match initial ORDER BY expressions
So how exactly do I go about doing this? Rawsql? Thanks!
If you use distinct by related model, you must use ordering based of this model:
Post.objects.order_by('chat', '-id').distinct('chat')
Also you can look at this question

What is the best way to use query with a list and keep the list order? [duplicate]

This question already has answers here:
Django: __in query lookup doesn't maintain the order in queryset
(6 answers)
Closed 8 years ago.
I've searched online and could only find one blog that seemed like a hackish attempt to keep the order of a query list. I was hoping to query using the ORM with a list of strings, but doing it that way does not keep the order of the list.
From what I understand bulk_query only works if you have the id's of the items you want to query.
Can anybody recommend an ideal way of querying by a list of strings and making sure the objects are kept in their proper order?
So in a perfect world I would be able to query a set of objects by doing something like this...
Entry.objects.filter(id__in=['list', 'of', 'strings'])
However, they do not keep order, so string could be before list etc...
The only work around I see, and I may just be tired or this may be perfectly acceptable I'm not sure is doing this...
for i in listOfStrings:
object = Object.objects.get(title=str(i))
myIterableCorrectOrderedList.append(object)
Thank you,
The problem with your solution is that it does a separate database query for each item.
This answer gives the right solution if you're using ids: use in_bulk to create a map between ids and items, and then reorder them as you wish.
If you're not using ids, you can just create the mapping yourself:
values = ['list', 'of', 'strings']
# one database query
entries = Entry.objects.filter(field__in=values)
# one trip through the list to create the mapping
entry_map = {entry.field: entry for entry in entries}
# one more trip through the list to build the ordered entries
ordered_entries = [entry_map[value] for value in values]
(You could save yourself a line by using index, as in this example, but since index is O(n) the performance will not be good for long lists.)
Remember that ultimately this is all done to a database; these operations get translated down to SQL somewhere.
Your Django query loosely translated into SQL would be something like:
SELECT * FROM entry_table e WHERE e.title IN ("list", "of", "strings");
So, in a way, your question is equivalent to asking how to ORDER BY the order something was specified in a WHERE clause. (Needless to say, I hope, this is a confusing request to write in SQL -- NOT the way it was designed to be used.)
You can do this in a couple of ways, as documented in some other answers on StackOverflow [1] [2]. However, as you can see, both rely on adding (temporary) information to the database in order to sort the selection.
Really, this should suggest the correct answer: the information you are sorting on should be in your database. Or, back in high-level Django-land, it should be in your models. Consider revising your models to save a timestamp or an ordering when the user adds favorites, if that's what you want to preserve.
Otherwise, you're stuck with one of the solutions that either grabs the unordered data from the db then "fixes" it in Python, or constructing your own SQL query and implementing your own ugly hack from one of the solutions I linked (don't do this).
tl;dr The "right" answer is to keep the sort order in the database; the "quick fix" is to massage the unsorted data from the database to your liking in Python.
EDIT: Apparently MySQL has some weird feature that will let you do this, if that happens to be your backend.

django : How to write alias in queryset

How can one write an alias for the column name in django query set.
Would be useful for union-style combinations of two linked field to the same foreign model (for instance).
for example in mysql :
select m as n, b as a from xyz
how can i do this in django query set ?
models.Table.objects.all().values('m', 'b')
Any help really appreciate it.
You can annotate the fields as you want, with the F expression:
from django.db.models import F
models.Table.objects.all().values('m', 'b').annotate(n=F('m'), a=F('b'))
Although this could have been done before by using extra(select={'n':'m','a':'b'}), I agree that this really should have been a part of values() itself.
To that end, and inspired by Alex's ticket, I have just posted a patch that adds this feature. I hope you'll find it useful!
Your reason in the comment makes no sense. Each field in the model has its own column in the database, and there's never any danger of mixing them up. You can of course tell a field to use a column name that's different from the field name:
myfield = models.CharField(max_length=10, db_column='differentname')
but I don't know if that will help you, because I still don't know what your problem is.
I'm presuming this isn't possible, so I've raised a ticket for the feature to be added, I think there is some merit to being able to do this. Please see the ticket for more information.
https://code.djangoproject.com/ticket/16735
you can also use .alias() in your queryset.
.alias(alias=SomeExpression()).annotate(
SomeOtherExpression('alias'))
.alias(alias=SomeExpression()).order_by('alias')
.alias(alias=SomeExpression()).update(field=F('alias'))
for your specific case, this would be the answer
models.Table.objects.all().alias(
n=F('m'), a=F('b')).values('m', 'a')
)
I really can't understand what you are trying to do however it sounds like what you are looking for is the extra queryset method. This for most purposes acts in the same manner as AS does in sql.