SQLAlchemy - WHERE子句中的子查询

Cha*_*rch 49 python sqlalchemy subquery

我刚刚开始使用SQLAlchemy,但仍然无法解决一些概念问题.

归结为基本元素,我有两个这样的表(这是通过Flask-SQLAlchemy):

class User(db.Model):
    __tablename__ = 'users'
    user_id = db.Column(db.Integer, primary_key=True)

class Posts(db.Model):
    __tablename__ = 'posts'
    post_id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.user_id'))
    post_time = db.Column(db.DateTime)

    user = db.relationship('User', backref='posts')
Run Code Online (Sandbox Code Playgroud)

我将如何查询用户列表及其最新帖子(不包括没有帖子的用户).如果我使用SQL,我会这样做:

SELECT [whatever]
FROM posts AS p
    LEFT JOIN users AS u ON u.user_id = p.user_id
WHERE p.post_time = (SELECT MAX(post_time) FROM posts WHERE user_id = u.user_id)
Run Code Online (Sandbox Code Playgroud)

所以我确切地知道"想要的"SQL以获得我想要的效果,但不知道如何在SQLAlchemy中"正确地"表达它.

编辑:如果它很重要,我在SQLAlchemy 0.6.6上.

zzz*_*eek 64

上一个答案是有效的,但你要求的确切sql写得与实际声明一样:

print s.query(User, Posts).\
    outerjoin(Posts.user).\
    filter(Posts.post_time==\
        s.query(
            func.max(Posts.post_time)
        ).
        filter(Posts.user_id==User.user_id).
        correlate(User).
        as_scalar()
    )
Run Code Online (Sandbox Code Playgroud)

我认为不一定明显的"概念"是as_scalar()目前需要将子查询建立为"标量"(它应该假设从上下文中反对==).

编辑:确认,这是错误行为,已完成票证#2190.在当前的提示或版本0.7.2中,自动调用as_scalar(),上述查询可以是:

print s.query(User, Posts).\
    outerjoin(Posts.user).\
    filter(Posts.post_time==\
        s.query(
            func.max(Posts.post_time)
        ).
        filter(Posts.user_id==User.user_id).
        correlate(User)
    )
Run Code Online (Sandbox Code Playgroud)


say*_*yap 57

这应该工作(不同的SQL,相同的结果):

t = Session.query(
    Posts.user_id,
    func.max(Posts.post_time).label('max_post_time'),
).group_by(Posts.user_id).subquery('t')

query = Session.query(User, Posts).filter(and_(
    User.user_id == Posts.user_id,
    User.user_id == t.c.user_id,
    Posts.post_time == t.c.max_post_time,
))

for user, post in query:
    print user.user_id, post.post_id
Run Code Online (Sandbox Code Playgroud)

其中c代表'列'