2011-06-01 154 views
34

我刚刚开始使用SQLAlchemy,并且在围绕某些概念时仍然遇到困难。SQLAlchemy - WHERE子句中的子查询

归结为基本元素,我有两个表是这样的(这是通过烧瓶的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') 

我怎么会去查询用户的列表和他们的最新职务(不包括没有帖子的用户)。如果我使用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) 

所以我确切地知道“期望” SQL得到我想要的效果,但不知道如何去表达它“正确”的SQLAlchemy的。

编辑:万一它很重要,我在SQLAlchemy 0.6.6。

回答

37

这应该工作(不同的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 
+5

什么是'C'在't.c.user_id'表示? – Rus925 2014-06-23 08:49:49

+4

'c'代表'列' – 10flow 2014-11-10 17:00:44

47

以前的答案工作,但你也要求写很多的实际语句的准确SQL:

print s.query(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() 
    ) 

我猜这个不一定明显的“概念”是as_scalar()当前需要将子查询建立为“标量”(它应该可能假定从==的上下文开始)。

编辑:确认,这是越野行为,已完成的票#2190。在当前的尖端或释放0.7.2中,as_scalar()被自动调用和上面的查询可以是:

print s.query(Posts).\ 
    outerjoin(Posts.user).\ 
    filter(Posts.post_time==\ 
     s.query(
      func.max(Posts.post_time) 
     ). 
     filter(Posts.user_id==User.user_id). 
     correlate(User) 
    )