【问题标题】:Count and group by foreign key and return model django通过外键计数和分组并返回模型django
【发布时间】:2019-04-20 11:40:14
【问题描述】:

数据模型:

  • 每个Library有很多Books
  • UserBookReceipt 指定的User 可能会或可能不会读取每个Book

目标:

给定一个用户,按照他们在每个图书馆阅读的书籍数量对图书馆进行排序。

示例:

用户 1 已阅读:

  • 图书馆 1 中的 2 本书
  • 图书馆 2 中的 5 本书
  • 图书馆 3 中的 1 本书
  • 图书馆 4 中的 0 本书

我们应该按照用户 1 阅读的书籍数量的顺序归还图书馆,即:

Library 2, Library 1, Library 3

当前解决方案

libraries = (UserBookReceipt.objects
    .filter(user=user)
    .values('book__library')
    .annotate(rcount=Count('book__library'))
    .order_by('-rcount')
)

实际输出

[
    {'book_library': 2, 'rcount': 5}, 
    {'book_library': 1, 'rcount': 2}, 
    {'book_library': 3, 'rcount': 1}
]

预期输出

[
    {'book_library': <Library: 2>, 'rcount': 5}, 
    {'book_library': <Library: 1>, 'rcount': 2}, 
    {'book_library': <Library: 3>, 'rcount': 1}
]

实际输出是我想要的 90%,除了我希望 book_library 值是 django Library 模型的实例,而不仅仅是库 id。否则,我必须进行另一个查询来检索 Library 对象,这可能需要一些低效的 ids__in query。

如何按UserBookReceipt.book__library 计数和分组并返回库模型?

如果我在 SQL 中执行此操作,查询将如下所示

with rcount_per_lib as (
    select lib.id, count(*) as rcount
    from lib, books, user_book_receipts
    where user_book_receipts.book_id = books.id
        and lib.id = books.lib_id 
        and user_book_receipts.user_id = 1
    group by lib.id)
select lib.*, rcount from rcount_per_lib 
where lib.id = rcount_per_lib.id 
order by rcount

【问题讨论】:

  • 如果你要使用 SQL,你真的应该使用正确、明确、标准 JOIN 语法。
  • 为什么? AFAIK and 语法在性能方面与 INNER JOIN 等效

标签: python sql django postgresql


【解决方案1】:

您需要更改处理查询集的方式。使用Library 而不是UserBookReceipt。

libraries = (Library.objects
    .filter(book__userbookreceipt__user=user)
    .annotate(rcount=Count('book__userbookreceipt', distinct=True))
    .order_by('-rcount')
)
[x.rcount for x in libraries]

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 1970-01-01
    • 2016-01-05
    • 1970-01-01
    • 2020-11-13
    • 2018-02-03
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    相关资源
    最近更新 更多