我们说我有一个作者表和一个帖子表,每个作者可以有几个帖子。
现在,通过单 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))
但是如果我有两个来自具有相同publish_date的作者的帖子,并且这些是最新的帖子,那意味着我在作品列表中出现两次该作者。虽然我可以使用第二个子查询来消除欺骗(使用func.max(Post.id)),但这似乎真的是非常错误的方法。有没有更好的方法来解决这个问题?
(同样,我正在寻找单个查询,所以我试图避免查询作者表,然后循环并对我的结果中的每个作者进行Post查询。)
答案 0 :(得分:7)
我会这样做:
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)
如您所见,结果为tuple
对(Author, LastPost)
如果您只想要至少有一个outerjoin
的作者,请将join
更改为Post
此外,我不预先加载任何关系Author.post
以避免任何混淆。