Open henriquebastos opened 11 years ago
Hi everyone. This issue is a big deal for me, so I'm willing to pay USD 40,00 for it. This offer is registered on FreedomSponsors (http://www.freedomsponsors.org/core/issue/363/add-support-for-conditions-involving-joins-with-aliases). If you solve it (according to the acceptance criteria described there), please register on FreedomSponsors and mark it as resolved there I'll then check it out and gladly pay up!
Oh, and if anyone else also wants throw in a few bucks on this, you should check out FreedomSponsors!
I've spent a few hours on it and seems like I've found some kind of solution of this issue, that works for me (Django 1.7). henriquebastos, could you please post more complete use case (Book model code, etc.), that i can test out on my own to ensure that I'm doing all the stuff correctly and that it works fine not only for my example? In my case I have this code:
# current_user is defined above as User instance and in this example current_user.id is 1.
users = User.objects.annotate(
messages_from_count=Count('chat_message_from_set', only=Q(chat_message_from_set__user_to=current_user)),
messages_to_count=Count('chat_message_to_set', only=Q(chat_message_to_set__user_from=current_user))
)
which resolves into:
SELECT
"cons_user"."id",
"cons_user"."auth_user_id",
"cons_user"."name",
"cons_user"."avatar",
COUNT (
CASE
WHEN "cons_chatmessage"."user_to_id" = 1 THEN
"cons_chatmessage"."id"
ELSE
NULL
END
) AS "messages_from_count",
COUNT (
CASE
WHEN "cons_chatmessage"."user_from_id" = 1 THEN
T5."id"
ELSE
NULL
END
) AS "messages_to_count"
FROM
"cons_user"
LEFT OUTER JOIN "cons_chatmessage" ON (
"cons_user"."id" = "cons_chatmessage"."user_from_id"
)
LEFT OUTER JOIN "cons_chatmessage" T5 ON (
"cons_user"."id" = T5."user_to_id"
)
GROUP BY
"cons_user"."id",
"cons_user"."auth_user_id",
"cons_user"."name",
"cons_user"."avatar";
which is not correct here:
WHEN "cons_chatmessage"."user_from_id" = 1 THEN
T5."id"
After fixing it, I've ended up with the following SQL code:
SELECT
"cons_user"."id",
"cons_user"."auth_user_id",
"cons_user"."name",
"cons_user"."avatar",
COUNT (
CASE
WHEN "cons_chatmessage"."user_to_id" = 1 THEN
"cons_chatmessage"."id"
ELSE
NULL
END
) AS "messages_from_count",
COUNT (
CASE
WHEN T5."user_from_id" = 1 THEN
T5."id"
ELSE
NULL
END
) AS "messages_to_count"
FROM
"cons_user"
LEFT OUTER JOIN "cons_chatmessage" ON (
"cons_user"."id" = "cons_chatmessage"."user_from_id"
)
LEFT OUTER JOIN "cons_chatmessage" T5 ON (
"cons_user"."id" = T5."user_to_id"
)
GROUP BY
"cons_user"."id",
"cons_user"."auth_user_id",
"cons_user"."name",
"cons_user"."avatar";
which is exactly what I want to get. Is there something similar in your case? My models looks like the following (unnecessary fields omitted):
class User(models.Model):
auth_user = models.OneToOneField(AuthUser, on_delete=models.CASCADE)
name = models.CharField(max_length=10)
avatar = models.ImageField(null=True, default=None, storage=AvatarStorage('user'))
class ChatMessage(models.Model):
user_from = models.ForeignKey(User, on_delete=models.CASCADE, related_name='chat_message_from_set')
user_to = models.ForeignKey(User, on_delete=models.CASCADE, related_name='chat_message_to_set')
Some queries relabel the table name with an alias, but aggregate-if can't follow it properly.
The generated query obtained by
print books.query
is:The problem is that the
WHEN
expression generated by theonly
argument is using the table nameaggregation_author
instead ofT5
.