我有以下查询集
photos = Photo.objects.all()
我过滤掉两个查询。
a = photos.filter(gallery__name='NGL')
b = photos.filter(gallery__name='NGA')
我将它们加在一起,形成一个新的更大的查询集。
c = a | b
实际上,a + b的长度等于c。
a.count() + b.count() == c.count()
>>> true
到目前为止一切顺利。然而,如果我引入.annotate(),|
似乎不再起作用。
one = photos.annotate(c=Count('label').exclude(c__lte=4)
two = photos.filter(painting=True)
all = one | two
one.count() + two.count() == all.count()
>>> False
即使正在使用.annotate()
,我如何组合查询集?请注意,只有在使用|
组合它们时,查询一和二都是按预期工作的,这似乎是错误的。
答案 0 :(得分:1)
用于组合查询集的管道|
或与号({1}}实际上将&
或OR
放入SQL查询,因此看起来像是组合。
AND
但是,当您结合使用更多过滤器并将其排除在外时,您可能会注意到,这样做会给您带来奇怪的结果。这就是为什么在比较计数时它不匹配的原因。
如果使用one = Photo.objects.filter(id=1)
two = Photo.objects.filter(id=2)
combined = one | two
print(combined.query)
>>> ... WHERE ("photo_photo"."id" = 1 OR "photo_photo"."id" = 2)...
,则必须具有相同数据类型的相同列,因此必须注释两个查询集。关于.union()
- .UNION()中的SELECT语句必须具有相同的列数
- 这些列还必须具有相似的数据类型
- 每个SELECT语句中的列也必须顺序相同
您必须记住,不确定数量的pythons参数.union()
是字典,因此,如果要对多个注释使用注释,则无法确保列的正确顺序。您可以通过链接注释命令解决此问题。
kwargs
然后您可以使用 # printed query of this won't be consistent
photo_queryset.annotate(label_count=Count('labels'), tag_count=Count('tags'))
# this will always have same order of columns
photo_queryset.annotate(label_count=Count('labels')).annotate(tag_count=Count('tags'))
,它不会弄乱注释的结果。同样,.union()
应该是最后一个方法,因为在.union()
之后,您不能使用类似.union()
的方法。如果您要保留重复项,请使用filter
,因为.union(qs, all=True)
具有默认的.union()
并在查询集上调用all=False
DISTINCT
然后它应该像您所描述的那样工作