我具有以下已构造的查询:
users = User.objects.filter(is_active=True)
date_range = [start_date, timezone.now()]
results = SurveyResult.objects.filter(
user__in=users,
created_date__range=date_range,
).annotate(
date=TruncDate('created_date'),
total_score=Sum('score'),
participants=Count('user'),
).values(
'survey',
'user',
'date',
'total_score',
'participants',
).order_by(
'date',
)
在结果QuerySet中将每个结果快速打印为:
for result in results:
print(results)
...以这种方式输出数据:
{'survey': UUID('eb51368e-994a-4c0b-8d8a-e00ed20b5926'), 'user': UUID('25afbbfd-bddf-4fe8-bbac-758bd96093b0'), 'date': datetime.date(2019, 7, 26), 'total_score': 90, 'participants': 1}
{'survey': UUID('09947780-8d60-499f-87e3-fc53a9490960'), 'user': UUID('6afdea22-ea10-4069-9e7b-43fb6955ce0e'), 'date': datetime.date(2019, 7, 26), 'total_score': 17, 'participants': 1}
{'survey': UUID('890d0a21-6e27-457f-902e-e2f37d2fad6c'), 'user': UUID('d98684f7-97ab-49d7-be50-0cc9b6465ef5'), 'date': datetime.date(2019, 7, 26), 'total_score': 35, 'participants': 1}
{'survey': UUID('890d0a21-6e27-457f-902e-e2f37d2fad6c'), 'user': UUID('d98684f7-97ab-49d7-be50-0cc9b6465ef5'), 'date': datetime.date(2019, 7, 27), 'total_score': 62, 'participants': 1}
老鹰眼中的您可能会注意到,最后两个记录在'user'和'survey'键上是伪重复的,而在其他任何一个上都没有。
我的问题是:如何从此记录集中删除记录(使用我构建的Django ORM查询或以标准的pythonic方式),其中“调查”键和“用户”键匹配-只保留根据“日期”的最新记录...所以离开我:
预期结果:
{'survey': UUID('eb51368e-994a-4c0b-8d8a-e00ed20b5926'), 'user': UUID('25afbbfd-bddf-4fe8-bbac-758bd96093b0'), 'date': datetime.date(2019, 7, 26), 'total_score': 90, 'participants': 1}
{'survey': UUID('09947780-8d60-499f-87e3-fc53a9490960'), 'user': UUID('6afdea22-ea10-4069-9e7b-43fb6955ce0e'), 'date': datetime.date(2019, 7, 26), 'total_score': 17, 'participants': 1}
{'survey': UUID('890d0a21-6e27-457f-902e-e2f37d2fad6c'), 'user': UUID('d98684f7-97ab-49d7-be50-0cc9b6465ef5'), 'date': datetime.date(2019, 7, 27), 'total_score': 62, 'participants': 1}
我尝试过的事情
我正在考虑也许利用这样的东西:
unique = { result['survey'] and result['user'] : result for result in results }.values()
答案 0 :(得分:0)
您已经明显拥有了想要的结果,因此您也可以在python中完成此操作,这几乎是您所建议的:
unique = {f"{result['survey']}+{result['user']}": result for result in results}.values()
尝试失败的原因是:您应该使用代表调查和用户的唯一密钥。使用and
,您将得到result['user']
,因为如果a and b
都为b
,则True
将返回latest_score
。
但是,我相信您的ORM查询有问题。您需要确保获得特定用户给出的created_date
,而不是给出分数的最后一天获得的分数之一(例如,您有两个得分不同的TruncDate
(不同时间)但是在date
之后,它们具有相同的results = SurveyResult.objects.filter(
user__in=users,
created_date__range=date_range,
).values(
'survey', 'user' # group by unique survey, user pair
).annotate(last_score=
Window(expression=LastValue('score'),
partition_by=[F('user'), F('survey')],
order_by=F('created_date').asc(),
)
).annotate(date=
Window(expression=LastValue(TruncDate('created_date')),
partition_by=[F('user'), F('survey')],
order_by=F('created_date').asc(),
)
).values(
'survey', 'user', 'date', 'last_score'
)
)。为了获得最后的分数,您应该尝试以下方法:
total_score
participants
和$scope.$apply(function () {
$scope.lists = res.lists;
});
并没有什么意义,因为分数只是用户最后一次为特定调查提供分数的那一行;参与者总是1。
如果您按调查和日期而不是调查和用户进行汇总,那将很有意义。