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)))
我的问题和
以下是相关模型的简化摘录:
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)))