SQL COUNT(DISTINCT <column>) 的 Django ORM 版本

Posted

技术标签:

【中文标题】SQL COUNT(DISTINCT <column>) 的 Django ORM 版本【英文标题】:Django ORM version of SQL COUNT(DISTINCT <column>) 【发布时间】:2013-01-28 04:29:22 【问题描述】:

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

这是模型的简化版本:

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?

【问题讨论】:

.distinct() 过滤器可能会派上用场。 如果我们忽略 COUNT(DISTINCT recipient_id),使用 annotate 和 Count 函数非常简单。在这里,django 的 distinct() 没有帮助。我认为不可能将这两件事(注释和不同)整合在一起。我猜你必须写两个查询。 【参考方案1】:

您确实可以同时使用 distinct 和 count ,如此答案所示:https://***.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))

【讨论】:

【参考方案2】:
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())

【讨论】:

谢谢!我是否正确理解这意味着数据库查询的数量与消息发送者的数量一样多(加一个)? @nephtes 是的。基本上我不认为有任何方法可以在 Count() 中使用 distinct()。也许,您最好使用原始 sql。我认为这是使用 django 的最佳方式,除非其他人想出更好的主意! @jurgenreza (我知道这篇文章很旧,但是......)我相信更好的方法是使用额外的:Message.objects.filter(...).extra('recipient_count' : 'COUNT(DISTINCT recipient_id)').values('recipient_count')。额外文档:docs.djangoproject.com/en/dev/ref/models/querysets/…

以上是关于SQL COUNT(DISTINCT <column>) 的 Django ORM 版本的主要内容,如果未能解决你的问题,请参考以下文章

SQL COUNT DISTINCT 函数

markdown sql,count,distinct

SELECT Count Distinct Syntax MS Access SQL [重复]

优化 COUNT(DISTINCT) SQL 查询

count(distinct) over (partition by... 在 Oracle SQL 中不起作用

如何在 SQL Server 中使用带有框架的窗口函数执行 COUNT(DISTINCT)