跨集合比较元素

时间:2016-03-11 10:51:54

标签: sql postgresql django-orm

我有以下型号:

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的回退也很好。

1 个答案:

答案 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,因为除了校验和比较,你必须回答“与什么不同?”