peewee - select 每个外键只有最新记录

peewee - select only latest record for each foreign key

我的问题和基本一样。 但是,我想在 Python 3.9 中使用 peewee 框架实现它。

以下是相关模型的简化摘录:

from datetime import datetime
from peewee import DateTimeField, ForeignkeyField, Model


class System(Model):
    ...


class CheckResults(Model):
    system = ForeignKeyField(System, column_name='system', on_delete='CASCADE')
    timestamp = DateTimeField(default=datetime.now)

到目前为止我尝试的是:

from peewee import fn

CheckResults.select().join(t2 := CheckResults.select(CheckResults.system, max_timestamp := fn.MAX(CheckResults.timestamp)).group_by(CheckResults.system), on=((t2.system == CheckResults.system) & (t2.timestamp == CheckResults.timestamp)))

这导致:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'ModelSelect' object has no attribute 'system'

如何在 peewee 中实现这样的复合查询?

在此处查看文档:http://docs.peewee-orm.com/en/latest/peewee/hacks.html#top-object-per-group

在这里我们将获取每个用户和他们发布的最新推文:

# When referencing a table multiple times, we'll call Model.alias() to create
# a secondary reference to the table.
TweetAlias = Tweet.alias()

# Create a subquery that will calculate the maximum Tweet created_date for each
# user.
subquery = (TweetAlias
            .select(
                TweetAlias.user,
                fn.MAX(TweetAlias.created_date).alias('max_ts'))
            .group_by(TweetAlias.user)
            .alias('tweet_max_subquery'))

# Query for tweets and join using the subquery to match the tweet's user
# and created_date.
query = (Tweet
         .select(Tweet, User)
         .join(User)
         .switch(Tweet)
         .join(subquery, on=(
             (Tweet.created_date == subquery.c.max_ts) &
             (Tweet.user == subquery.c.user_id))))

SQLite 和 MySQL 更宽松一些,允许按所选列的子集进行分组。这意味着我们可以取消子查询并非常简洁地表达它:

query = (Tweet
         .select(Tweet, User)
         .join(User)
         .group_by(Tweet.user)
         .having(Tweet.created_date == fn.MAX(Tweet.created_date)))