我有以下型号:
class Collection(models.Model):
...
class Record(models.Model):
collection = models.ForeignKey(Collection, related_name='records')
filename = models.CharField(max_length=256)
checksum = models.CharField(max_length=64)
class Meta:
unique_together = (('filename', 'collection'),)
我想执行以下查询:
对于filename
Record
的每个Collections
,我想知道Record
:
Record
checksum
但具有不同的 | C1 C2 C3 <- collections
-----------+------------
file-1.txt | x
file-2.txt | x
file-3.txt | ! ! !
file-4.txt | x ! !
file-5.txt | ! ! x
x = missing
! = different checksum
我想到了这样的输出:
Collection
到目前为止我所说的是我为每个for collection in collections:
other_collections = [c for c in collections if c is not collection]
results[collection] = qs.filter(collection__in=other_collections).exclude(
filename__in=qs.filter(
collection=collection
).values_list('filename', flat=True)
).order_by('filename').values_list('filename', flat=True)
创建了一个查询,不包括此集合中但存在于其他文件中的所有文件名。
checksum
这在某种程度上解决了我问题的第一部分,但是相当古怪,需要进行后期处理才能达到我想要的格式。而且,更重要的是,它没有涉及QuerySet
比较。
是否可以在一个组合步骤中执行两个查询以获得上述格式的结果?
解决方案不一定非必须使用{{1}} API,对原始SQL的回退也很好。
答案 0 :(得分:1)
无法编写返回可变数量列的SQL查询,但如果将所有内容都包装在an array或JSON对象中,则可以实现此效果。
如果您知道集合,可以像这样编写SQL:
SELECT r.filename,
(SELECT r.checksum = r2.checksum FROM records r2 WHERE r.filename = r2.filename AND r2.collection_id = 1) AS c1,
(SELECT r.checksum = r2.checksum FROM records r2 WHERE r.filename = r2.filename AND r2.collection_id = 2) AS c2,
...
FROM records r
WHERE r.collection_id = 1
GROUP BY r.filename, r.checksum
对于每个文件名/集合对,如果集合没有记录,您将获得NULL
,如果集合具有正确的校验和,则将获得true
,或者false
该集合具有不同的校验和。
我包含WHERE r.collection_id = 1
,因为除了校验和比较,你必须回答“与什么不同?”