11

我需要在一个简单的消息传递系统中填写一个包含用户活动摘要的模板。对于每个消息发件人,我想要发送的消息数量和不同收件人的数量。

这是模型的简化版本:

class Message(models.Model):
    sender = models.ForeignKey(User, related_name='messages_from')
    recipient = models.ForeignKey(User, related_name='messages_to')
    timestamp = models.DateTimeField(auto_now_add=True)

下面是我在 SQL 中的做法:

SELECT sender_id, COUNT(id), COUNT(DISTINCT recipient_id)
    FROM myapp_messages
    GROUP BY sender_id;

我一直在阅读有关 ORM 查询中聚合的文档,尽管 annotate() 可以处理第一个 COUNT 列,但我看不到获得 COUNT(DISTINCT) 结果的方法(甚至是额外的(select={})一直没有工作,虽然它似乎应该)。这可以翻译成 Django ORM 查询还是我应该坚持使用原始 SQL?

4

2 回答 2

9

您确实可以同时使用 distinct 和 count ,如此答案所示:https ://stackoverflow.com/a/13145407/237091

在你的情况下:

SELECT sender_id, COUNT(id), COUNT(DISTINCT recipient_id)
FROM myapp_messages
GROUP BY sender_id;

会成为:

Message.objects.values('sender').annotate(
    message_count=Count('sender'),
    recipient_count=Count('recipient', distinct=True))
于 2014-04-07T17:55:33.277 回答
4
from django.db.models import Count

messages = Message.objects.values('sender').annotate(message_count=Count('sender'))

for m in messages:
    m['recipient_count'] = len(Message.objects.filter(sender=m['sender']).\
                              values_list('recipient', flat=True).distinct())
于 2013-02-12T19:25:44.380 回答