简体   繁体   English

Django - 如何编写与此 SQL 查询等效的查询集? - 使用计数和 FIRST_VALUE 管理重复项

[英]Django - How do I write a queryset that's equivalent to this SQL query? - Manging duplicates with Counting and FIRST_VALUE

I have Model "A" that both relates to another model and acts as a public face to the actual data (Model "B"), users can modify the contents of A but not of B.我有模型“A”,它既与另一个模型相关,又作为实际数据的公众面孔(模型“B”),用户可以修改 A 的内容,但不能修改 B 的内容。

For every B there can be many As, and they have a one to many relation.对于每个 B,可以有多个 As,并且它们具有一对多的关系。

When I display this model anytime there's two or more A's related to the BI see "duplicate" records with (almost always) the same data, a bad experience.当我在任何时候显示此模型时,有两个或更多与 BI 相关的 A 会看到具有(几乎总是)相同数据的“重复”记录,这是一种糟糕的体验。

I want to return a queryset of A items that relate to the B items, and when there's more than one roll them up to the first entered item.我想返回与 B 项目相关的 A 项目的查询集,并且当有多个将它们汇总到第一个输入的项目时。

I also want to count the related model B items and return that count to give me an indication of how much duplication is available.我还想计算相关的模型 B 项目并返回该计数以指示有多少重复可用。

I wrote the following analogous SQL query which counts the related items and uses first_value to find the first A created partitioned by B.我编写了以下类似的 SQL 查询,它计算相关项目并使用 first_value 查找由 B 创建的第一个 A 创建分区。

SELECT *
FROM 
(
  SELECT                         
    COUNT(*) OVER (PARTITION BY b_id) as count_related_items,
    FIRST_VALUE(id) OVER (PARTITION BY b_id order by created_time ASC) as first_filter,                       
    *
  FROM A 
) AS A1 
WHERE 
A1.first_filter = A1.id;

As requested, here's a simplified view of the models:根据要求,这是模型的简化视图:

class CoreData(models.Model):
    title = models.CharField(max_length=500)    

class UserData(models.Model):

    core = models.ForeignKey("CoreData", on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    title = models.CharField(max_length=500)
    

When a user creates data it first checks/creates the CoreData, storing things like the title, and then it creates the UserData, with a reference to the CoreData.当用户创建数据时,它首先检查/创建 CoreData,存储标题等内容,然后创建 UserData,并引用 CoreData。 When a second user creates a piece of data and it references the same CoreData is when the "duplication" is introduced and why you can roll up the UserData (in SQL) to find the count and the "first" entry in the one to many relation.当第二个用户创建一条数据并引用相同的 CoreData 时,就是引入了“重复”以及为什么可以汇总 UserData(在 SQL 中)以在一对多中查找计数和“第一个”条目关系。

Assuming my understanding is correct -假设我的理解是正确的-

If you are querying from the UserData model the query would look something like this:如果您从 UserData 模型查询,则查询将如下所示:

Considering CoreData.id = 18考虑 CoreData.id = 18

user_data = UserData.objects.filter(core__id=18).
order_by("created_time").annotate(duplicate_count=Count('core__userData', filter(core__id=18))).first()

user_data would be the First object created which is related to the CoreData object. user_data将是第一个创建的与 CoreData 对象相关的对象。 Also,还,

user_data.duplicate_count will give you the Count of UserData objects that are related to the CoreData object. user_data.duplicate_count将为您提供与 CoreData 对象相关的 UserData 对象的计数。

Reference Docs on Annotate here此处注释的参考文档

Update:更新:

If you need the list of UserData of specific CoreData you could use如果您需要特定 CoreData 的 UserData 列表,您可以使用

user_data = UserData.objects.filter(core__id=18).
order_by("created_time").annotate(duplicate_count=Count('core__UserData', filter(core__id=18)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM