【问题标题】:Comparing Elements across collections比较集合中的元素
【发布时间】:2016-03-11 10:51:53
【问题描述】:

我有以下型号:

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'),)

我想执行以下查询:

对于Record 中的每个filename,我想知道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 API,我也可以回退到原始 SQL。

【问题讨论】:

    标签: sql postgresql django-orm


    【解决方案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,否则对于校验和比较,您必须回答“与什么不同?”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多