gpt4 book ai didi

mysql - 在 Django 中使用带有 GROUP BY 子句的 COUNT(DISTINCT 字段)

转载 作者:行者123 更新时间:2023-11-29 01:42:02 24 4
gpt4 key购买 nike

问题

我想在 Django 中使用 COUNT(DISTINCT field)GROUP BY 子句。据我了解,COUNT(DISTINCT... 只能通过对查询集使用 extra 来实现。

我的简化模型是:

class Site(models.Model):
name = models.CharField(max_length=128, unique=True)

class Application(models.Model):
name = models.CharField(max_length=64)
version = models.CharField(max_length=13, db_index=True)

class User(models.Model):
name = models.CharField(max_length=64)
site = models.ForeignKey(Site, db_index=True)

class Device(models.Model):
imei = models.CharField(max_length=16, unique=True)

applications = models.ManyToManyField(Application, null=True, db_index=True, through='ApplicationUsage')
user = models.ForeignKey(User, null=True, db_index=True)

class ApplicationUsage(models.Model):
activity = models.DateField(db_index=True)

application = models.ForeignKey(Application)
device = models.ForeignKey(Device)

我的目标是在给定某个时间段内的应用程序事件的情况下,为每个站点创建一个站点对象列表,其中包含不同设备的数量,例如

stats_site.name     deviceCount
ALBI 32
AMPLEPUIS 42
...

我试试这段代码:

qs = models.Site.objects.filter(user__device__applicationusage__activity__range=[startDay, endDay])\
.extra(select={'deviceCount' : 'COUNT(DISTINCT `stats_device`.`id`)'})\
.values('name', 'deviceCount')\

生成的 SQL 是:

SELECT (COUNT(DISTINCT stats_device.id)) AS deviceCount, stats_site.name
FROM stats_site
INNER JOIN stats_user ON (stats_site.id = stats_user.site_id)
INNER JOIN stats_device ON (stats_user.id = stats_device.user_id)
INNER JOIN stats_applicationusage ON (stats_device.id = stats_applicationusage.device_id)
WHERE stats_applicationusage.activity BETWEEN '2013-07-01' AND '2013-07-03'

结果显然是错误的,因为它缺少 GROUP BY 子句,应该是 GROUP BY stats_site.name

问题是:我不知道如何使用 annotate 函数或其他函数添加正确的 GROUP BY

解决方案

Count 函数上使用 distinct=Trueannotate:

qs = models.Site.objects.filter(habileouser__device__applicationusage__activity__range=[startDay, endDay])\
.annotate(deviceCount=Count('habileouser__device', distinct=True))\
.values('name', 'deviceCount')

最佳答案

查询集的 annotate 方法将为查询集的每个元素计算聚合值,并且在 values 调用之后使用时将聚合值的值.我认为这应该有效:

qs = models.Site.objects.filter(
user__device__applicationusage__activity__range=[startDay, endDay]
).values('name').annotate(Count('user__device', distinct=True))

如果您指定了顺序,您可能需要按照此处的讨论将其删除: https://docs.djangoproject.com/en/dev/topics/db/aggregation/#interaction-with-default-ordering-or-order-by

关于mysql - 在 Django 中使用带有 GROUP BY 子句的 COUNT(DISTINCT 字段),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18451667/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com