小编典典

使用sqlalchemy从相关表中仅选择一行

sql

假设我有一个Author表和一个Post表,每个Author可以有多个Post。

现在,随着单SQLAlchemy的查询,我想我所有的活跃作者和最近发布的帖子为每个。

我一直在尝试通过获取子列表来加入作者的工作列表,使用子查询将结果分组在一起,如下所示:

subquery = DBSession.query(Author.id, func.max(Post.publish_date).label("publish_date")) \
    .join(Post.author) \
    .filter(Post.state == 'published') \
    .filter(Author.state == 'active') \
    .group_by(Author.id) \
    .subquery()

query = DBSession.query(Post) \
    .options(joinedload(Post.author)) \
    .join(Post.author) \
    .join(subquery, and_(Author.id == subquery.c.id, 
                         Post.publish_date == subquery.c.publish_date))

但是,如果我有两个来自同一发布日期的Author帖子,而这些帖子是最新的Posts,则意味着我得到那个Author在我的结果列表中出现两次。虽然我可以使用第二个子查询来消除重复(使用func.max(Post.id)),但这似乎是一种非常错误的方式。有更好的方法来解决这个问题吗?

(再次,我正在寻找一个查询,所以我试图避免在Author表上查询,然后遍历并对结果中的每个Author进行Post查询。)


阅读 168

收藏
2021-05-05

共1个答案

小编典典

我将按以下方式进行操作:

LastPost = aliased(Post, name='last')
last_id = (
    session.query(LastPost.id)
    .filter(LastPost.author_id == Author.id)
    .order_by(LastPost.publish_date.desc())
    .order_by(LastPost.id.desc())
    .limit(1)
    .correlate(Author)
    .as_scalar()
)

query = (
    DBSession.query(Author, Post)
    .outerjoin(Post, Post.id == last_id)
)

for author, last_post in query:
    print(author, last_post)

如您所见,结果是atuple(Author, LastPost)。如果只希望作者至少有一位,请
更改outerjoin为。 另外,我不会预先加载任何关系,以免造成任何混乱。joinPost Author.post

2021-05-05