如何使用 Django 模型将 "annotate" 数据添加到多个 "values" 的查询中?
How to add "annotate" data into query with several "values" with django models?
示例模型:
class A(models.Model):
id = models.CharField(max_length=255, primary_key=True, default=make_uuid, editable=False)
b = models.IntegerField()
目标:
我需要获取包含 id
、b
和 same_b_total
.
的列表
例如以下查询集 returns:
a = list(models.Cell.objects.all().values("b").annotate(same_b_total=Count("b")))
print(a) # [{"b": 1, "same_b_total": 5}, {"b": 2, "same_b_total": 3}]
当我将 id
添加到 .values("b", "id")
中时,它 return 列出了后续数据
[{'b': 1, 'id': '<some uuid>', 'same_b_total': 1}, {'b': 1, 'id': '<some uuid2>', 'same_b_total': 1}, {'b': 2, 'id': '<some uuid3>', 'same_b_total': 1}, ...]
如何更改查询以接收每条记录的正确 same_b_total
? 赞:
[{'b': 1, 'id': '<some uuid>', 'same_b_total': 5}, {'b': 1, 'id': '<some uuid2>', 'same_b_total': 5}, {'b': 2, 'id': '<some uuid3>', 'same_b_total': 3}, ...]
Table 示例:
编号(uuid)| b
uuid-1 | 1
uuid-2 | 1
uuid-3 | 2
uuid-4 | 1
uuid-5 | 1
uuid-6 | 1
uuid-7 | 2
uuid-8 | 2
说明
使用 OuterRef
和 Subquery
的组合就是您要寻找的。
对于 b
字段的特定整数值,您需要获取所有现有行的计数。通过用 OuterRef('b')
替换特定的整数值,结果将转换为子查询。 (而不是普通的查询集)
请注意 sub
是一个子查询,它本身并不存在。
sub = A.objects.filter(b=OuterRef('b')).values('b').annotate(same_b_count=Count('id'))
我们需要将 sub
注入另一个查询。从 Django docs 获得一些关于 Subquery
和 Outerref
组合的帮助导致:
A.objects.annotate(same_b_count=Subquery(sub.values('same_b_count'))).values('id', 'b', 'same_b_count')
结论
合并解释中的两个片段:
sub = A.objects.filter(b=OuterRef('b')).values('b').annotate(same_b_count=Count('id'))
A.objects.annotate(same_b_count=Subquery(sub.values('same_b_count'))).values('id', 'b', 'same_b_count')
将导致输出:
<QuerySet [{'id': 1, 'b': 1, 'same_b_count': 3}, {'id': 2, 'b': 1, 'same_b_count': 3}, {'id': 3, 'b': 1, 'same_b_count': 3}, {'id': 4, 'b': 3, 'same_b_count': 1}, {'id': 5, 'b': 4, 'same_b_count': 2}, {'id': 6, 'b': 4, 'same_b_count': 2}, {'id': 7, 'b': 6, 'same_b_count': 1}]>
示例模型:
class A(models.Model):
id = models.CharField(max_length=255, primary_key=True, default=make_uuid, editable=False)
b = models.IntegerField()
目标:
我需要获取包含 id
、b
和 same_b_total
.
例如以下查询集 returns:
a = list(models.Cell.objects.all().values("b").annotate(same_b_total=Count("b")))
print(a) # [{"b": 1, "same_b_total": 5}, {"b": 2, "same_b_total": 3}]
当我将 id
添加到 .values("b", "id")
中时,它 return 列出了后续数据
[{'b': 1, 'id': '<some uuid>', 'same_b_total': 1}, {'b': 1, 'id': '<some uuid2>', 'same_b_total': 1}, {'b': 2, 'id': '<some uuid3>', 'same_b_total': 1}, ...]
如何更改查询以接收每条记录的正确 same_b_total
? 赞:
[{'b': 1, 'id': '<some uuid>', 'same_b_total': 5}, {'b': 1, 'id': '<some uuid2>', 'same_b_total': 5}, {'b': 2, 'id': '<some uuid3>', 'same_b_total': 3}, ...]
Table 示例:
编号(uuid)| b
uuid-1 | 1
uuid-2 | 1
uuid-3 | 2
uuid-4 | 1
uuid-5 | 1
uuid-6 | 1
uuid-7 | 2
uuid-8 | 2
说明
使用 OuterRef
和 Subquery
的组合就是您要寻找的。
对于 b
字段的特定整数值,您需要获取所有现有行的计数。通过用 OuterRef('b')
替换特定的整数值,结果将转换为子查询。 (而不是普通的查询集)
请注意 sub
是一个子查询,它本身并不存在。
sub = A.objects.filter(b=OuterRef('b')).values('b').annotate(same_b_count=Count('id'))
我们需要将 sub
注入另一个查询。从 Django docs 获得一些关于 Subquery
和 Outerref
组合的帮助导致:
A.objects.annotate(same_b_count=Subquery(sub.values('same_b_count'))).values('id', 'b', 'same_b_count')
结论
合并解释中的两个片段:
sub = A.objects.filter(b=OuterRef('b')).values('b').annotate(same_b_count=Count('id'))
A.objects.annotate(same_b_count=Subquery(sub.values('same_b_count'))).values('id', 'b', 'same_b_count')
将导致输出:
<QuerySet [{'id': 1, 'b': 1, 'same_b_count': 3}, {'id': 2, 'b': 1, 'same_b_count': 3}, {'id': 3, 'b': 1, 'same_b_count': 3}, {'id': 4, 'b': 3, 'same_b_count': 1}, {'id': 5, 'b': 4, 'same_b_count': 2}, {'id': 6, 'b': 4, 'same_b_count': 2}, {'id': 7, 'b': 6, 'same_b_count': 1}]>