python - 使用 sqlalchemy 从相关表中只选择一行

标签 python sqlalchemy

假设我有一个 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))

但是如果我有两篇来自同一作者的具有相同 publish_date 的帖子,并且这些帖子是最新的帖子,这意味着我让该作者在我的结果列表中出现了两次。虽然我可以使用第二个子查询来消除重复项(采用 func.max(Post.id)),但看起来确实是错误的方法。有没有更好的方法来解决这个问题?

(同样,我正在寻找单个查询,所以我试图避免在 Author 表上查询,然后循环遍历并对结果中的每个 Author 执行 Post 查询。)

最佳答案

我会这样做:

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)

如您所见,结果是 元组(Author, LastPost)
如果您只想要至少有一个 Post 的作者,请将 outerjoin 更改为 join
此外,我不预加载任何关系 Author.post 以避免任何混淆。

关于python - 使用 sqlalchemy 从相关表中只选择一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26396629/

相关文章:

python - 使 Django 管理员显示主键而不是每个对象的对象类型

Python - 属性错误 : 'NoneType' object has no attribute 'get_text'

Python3 : How do I import an excel spreadsheet into python project?(我使用 repl.it 网站学习 python3)

python - 如何获得没有填充的标记,来自seaborn 0.11+

python - Django 提取值并使它们成为另一个页面中的占位符

python - Psycopg2 或 SQLAlchemy 中的多个 SELECT

python - 返回两个串联的 SqlAlchemy 列

python - 如何从 SQLAlchemy 表达式中获取原始的、已编译的 SQL 查询?

python - 如何使 SQLAlchemy 插入与 Postgres 多处理证明 upsert 触发器一起工作?

python - 带有 SQLAlchemy 的 Postgres 中的枚举数组