SQLAlchemy过滤相关对象的查询

Mar*_*arc 16 python sqlalchemy

使用SQLAlchemy,我与两个表有一对多的关系 - 用户和分数.我试图查询排名前10位的用户,这些用户按过去X天的总分进行排序.

users:  
  id  
  user_name  
  score  

scores:  
  user   
  score_amount  
  created  
Run Code Online (Sandbox Code Playgroud)

我目前的查询是:

 top_users = DBSession.query(User).options(eagerload('scores')).filter_by(User.scores.created > somedate).order_by(func.sum(User.scores).desc()).all()  
Run Code Online (Sandbox Code Playgroud)

我知道这显然不正确,这只是我最好的猜测.但是,在查看文档和谷歌搜索后,我找不到答案.

编辑:如果我勾勒出MySQL查询的样子,也许会有所帮助:

SELECT user.*, SUM(scores.amount) as score_increase 
FROM user LEFT JOIN scores ON scores.user_id = user.user_id 
WITH scores.created_at > someday 
ORDER BY score_increase DESC
Run Code Online (Sandbox Code Playgroud)

zzz*_*eek 21

单连接行方式,group_by为所有用户列添加了一个,但如果您选择,MySQL将允许您在"id"列上进行分组:

    sess.query(User, func.sum(Score.amount).label('score_increase')).\
               join(User.scores).\
               filter(Score.created_at > someday).\
               group_by(User).\
               order_by("score increase desc")
Run Code Online (Sandbox Code Playgroud)

或者,如果您只想在结果中使用用户:

sess.query(User).\
           join(User.scores).\
           filter(Score.created_at > someday).\
           group_by(User).\
           order_by(func.sum(Score.amount))
Run Code Online (Sandbox Code Playgroud)

上面两个的效率很低,因为你在"用户"的所有列上进行分组(或者你只使用MySQL的"几列上的组",这只是MySQL).为了最小化,子查询方法:

subq = sess.query(Score.user_id, func.sum(Score.amount).label('score_increase')).\
                  filter(Score.created_at > someday).\
                  group_by(Score.user_id).subquery()
sess.query(User).join((subq, subq.c.user_id==User.user_id)).order_by(subq.c.score_increase)
Run Code Online (Sandbox Code Playgroud)

相同场景的一个示例位于ORM教程中:http: //docs.sqlalchemy.org/en/latest/orm/tutorial.html#selecting-entities-from-subqueries