2011-06-01 116 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) 
    )