I';我对distinct()如何处理Django查询感到困惑

I';我对distinct()如何处理Django查询感到困惑,django,django-queryset,django-nonrel,Django,Django Queryset,Django Nonrel,我有一个疑问: checkins = CheckinAct.objects.filter(time__range=[start, end], location=checkin.location) 这对于告诉我某个特定地点在我的日期范围内发生了多少次签入非常有用。但我想知道有多少签入是由唯一用户完成的。所以我试了一下: checkins = CheckinAct.objects.filter(time__range=[start, end], location=checkin.location)

我有一个疑问:

checkins = CheckinAct.objects.filter(time__range=[start, end], location=checkin.location)
这对于告诉我某个特定地点在我的日期范围内发生了多少次签入非常有用。但我想知道有多少签入是由唯一用户完成的。所以我试了一下:

checkins = CheckinAct.objects.filter(time__range=[start, end], location=checkin.location).values('user').distinct()
但这不起作用,我得到一个空数组。你知道为什么吗

这是我的CheckinAct模型:

class CheckinAct(models.Model):
    user = models.ForeignKey(User)
    location = models.ForeignKey(Location)
    time = models.DateTimeField()
----更新------ 现在我更新了查询,如下所示:

 checkins = CheckinAct.objects.values('user').\
                            filter(time__range=[start, end], location=checkin.location).\
                            annotate(dcount=Count('user'))
但我仍然得到多个具有相同用户的对象,如下所示:

 [{'user': 15521L}, {'user': 15521L}, {'user': 15521L}, {'user': 15521L}, {'user': 15521L}]
----更新2------ 这里还有一些我尝试过的东西,但是当我记录checkins对象时,我仍然得到很多相同的用户对象

checkins = CheckinAct.objects.filter(
                    time__range=[start, end],
                    location=checkin.location,
                ).annotate(dcount=Count('user')).values('user', 'dcount')
        logger.info("checkins!!! : " + str(checkins))
记录以下内容:

checkins!!! : [{'user': 15521L}, {'user': 15521L}, {'user': 15521L}]

请注意,同一用户对象有3个实例。这是否正常工作?读取dict对象中返回的内容有不同的方法吗?我只需要知道在这个时间范围内有多少个独特的用户登录到这个特定的位置。

你不希望
与众不同。实际上,您希望Django做一些事情,最终为您提供一个
GROUPBY
子句。同样正确的是,您的最终解决方案是组合
annotate()
values()
,如前所述

要获得结果,您需要先使用
注释
,然后使用
,例如:

CheckinAct.objects.filter(
    time__range=[start, end],
    location=checkin.location,
).annotate(dcount=Count('user').values('user', 'dcount')
我在上面给你的链接中的Django文档显示了一个构造类似的查询(减去我在适当位置为你的案例添加的
过滤器
方面),并注意到这将“现在为每个[checkin act]生成一个唯一的结果;但是,只有[user]和[
dcount
]注释将在“输出数据”中返回。(我根据你的情况编辑了这句话,但原则是一样的)


希望有帮助

您不希望
不同
。实际上,您希望Django做一些事情,最终为您提供一个
GROUPBY
子句。同样正确的是,您的最终解决方案是组合
annotate()
values()
,如前所述

checkins = CheckinAct.objects.values('user').\
                        filter(time__range=[start, end], location=checkin.location).\
                        annotate(dcount=Count('user'))
要获得结果,您需要先使用
注释
,然后使用
,例如:

CheckinAct.objects.filter(
    time__range=[start, end],
    location=checkin.location,
).annotate(dcount=Count('user').values('user', 'dcount')
我在上面给你的链接中的Django文档显示了一个构造类似的查询(减去我在适当位置为你的案例添加的
过滤器
方面),并注意到这将“现在为每个[checkin act]生成一个唯一的结果;但是,只有[user]和[
dcount
]注释将在“输出数据”中返回。(我根据你的情况编辑了这句话,但原则是一样的)

希望有帮助

checkins = CheckinAct.objects.values('user').\
                        filter(time__range=[start, end], location=checkin.location).\
                        annotate(dcount=Count('user'))
如果我没有弄错的话,您想要的值不是作为“dcount”出现在输入中吗?因此,当您决定单独输出用户值时,这不是被丢弃了吗

你能告诉我当你尝试这个的时候会发生什么吗

checkins = CheckinAct.objects.values('user').\
                        filter(time__range=[start, end], location=checkin.location).\
                        annotate(Count('user')).order_by()
(最后一个命令是清除您在模型级别可能已经拥有的任何内置命令-不确定您是否拥有类似的命令,但询问也无妨……)

如果我没有弄错的话,您想要的值不是作为“dcount”出现在输入中吗?因此,当您决定单独输出用户值时,这不是被丢弃了吗

你能告诉我当你尝试这个的时候会发生什么吗

checkins = CheckinAct.objects.values('user').\
                        filter(time__range=[start, end], location=checkin.location).\
                        annotate(Count('user')).order_by()

(最后一个命令是清除您在模型级别可能已经拥有的任何内置命令-不确定您是否有类似的命令,但询问也无妨…

答案实际上是正确的。不幸的是,很少有人注意到你需要的特定部分的重要性;因此,这是可以理解的错过。(往下读一点关于
项目的部分)

对于您的用例,以下内容应该为您提供您想要的:

checkins = CheckinAct.objects.filter(time__range=[start,end], location=checkin.location).\
                              values('user').annotate(checkin_count=Count('pk')).order_by()
更新

根据你的评论,我认为你想要实现什么的问题一直都很困惑。上面的查询为您提供了一个列表,其中列出了每个用户在某个位置签入的次数,该列表中没有重复的用户。现在看来,您真正想要的是在某个特定位置签入的唯一用户的数量。要实现这一点,请使用以下方法(无论如何都要简单得多):

非rel支持更新

checkin_users = [(c.user.pk, c.user) for c in CheckinAct.objects.filter(location=location)]
unique_checkins = len(dict(checkin_users))

这是基于
dict
s具有唯一键的原理。因此,当您将元组列表转换为dict时,您将得到一个唯一用户列表。但是,这将生成1*N个查询,其中N是签入的总数(每次使用
user
属性时,都会进行一次查询。通常,我会执行类似
的操作。选择\u related('user'))
,但这也需要一个连接,这显然是错误的。不受支持的连接对于非rel来说似乎是一个巨大的缺点,如果是真的,但如果是这样的话,这将是你唯一的选择。

答案实际上是正确的。不幸的是,很少有人注意到特定部分的重要性你需要;所以它被遗漏了,这是可以理解的

对于您的用例,以下内容应该为您提供您想要的:

checkins = CheckinAct.objects.filter(time__range=[start,end], location=checkin.location).\
                              values('user').annotate(checkin_count=Count('pk')).order_by()
更新

根据你的评论,我认为你想要实现的问题一直都很困惑。上面的查询提供给你的是一个列表,列出了每个用户在某个位置签入的次数,该列表中没有重复的用户。现在看来,你真正想要的是在某个特定位置签入的唯一用户的数量n、 要实现这一点,请使用以下方法(无论如何都要简单得多):

非rel支持更新

checkin_users = [(c.user.pk, c.user) for c in CheckinAct.objects.filter(location=location)]
unique_checkins = len(dict(checkin_users))
这是根据
dict
s具有唯一键的原则进行的。因此,当您将元组列表转换为dict时,最终将得到一个唯一用户列表。但是,这将生成1*N个查询,其中N是签入的总数(一个查询