Requête de filtre SQLAlchemy par objet associé
À l'aide de SQLAlchemyj'ai une relation un à plusieurs avec deux tables - les utilisateurs et les scores. Je suis en train d'interroger le top 10 des utilisateurs triés en fonction de leur score total au cours de la dernière quantité de X jours.
users:
id
user_name
score
scores:
user
score_amount
created
Ma question est:
top_users = DBSession.query(User).options(eagerload('scores')).filter_by(User.scores.created > somedate).order_by(func.sum(User.scores).desc()).all()
Je sais que ce n'est clairement pas correct, c'est juste ma meilleure supposition. Toutefois, après avoir examiné la documentation et de recherches sur google je ne trouve pas de réponse.
EDIT:
Peut-être qu'il serait utile que je viens de décrire ce que l' MySQL requête devrait ressembler à:
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
source d'informationauteur Marc
Vous devez vous connecter pour publier un commentaire.
La seule joint-ligne, avec un
group_by
ajoutée pour tous les utilisateurs colonnes bien que MySQL va vous permettre de groupe sur le "id" de la colonne si elle est à vous de choisir:Ou si vous voulez juste les utilisateurs dans le résultat:
Les deux ci-dessus ont une inefficacité dans que vous êtes regroupement sur toutes les colonnes de "l'utilisateur" (ou si vous utilisez MySQL-groupe sur seulement quelques colonnes" chose, qui est de MySQL uniquement). Pour minimiser cela, la sous-requête approche:
Un exemple de l'identique le scénario est dans l'ORM tutoriel: http://docs.sqlalchemy.org/en/latest/orm/tutorial.html#selecting-entities-from-subqueries
Vous aurez besoin d'utiliser une sous-requête pour calculer le score total pour chaque utilisateur. Les sous-requêtes sont décrites ici: http://www.sqlalchemy.org/docs/05/ormtutorial.html?highlight=subquery#using-subqueries
Je suis en supposant que la colonne (pas le lien) que vous utilisez pour la jointure est appelé Score.user_id, afin de la modifier si ce n'est pas le cas.
Vous aurez besoin de faire quelque chose comme ceci:
Sera toutefois des tuples de (user_id, total_score). Je ne suis pas sûr si le score calculé est réellement important pour vous, mais si elle l'est, vous aurez probablement envie de faire quelque chose comme ceci:
Il en résultera 11 requêtes en cours d'exécution, cependant. Il est possible de tout faire en une seule requête, mais en raison de plusieurs restrictions dans SQLAlchemy, il est susceptible de générer une très laid multi-requête de jointure ou une sous-requête (en fonction du moteur) et il ne sera pas très performant.
Si vous projetez de faire quelque chose comme cela, souvent, et vous avez une grande quantité de scores, envisagez la dénormalisation le score actuel sur la table utilisateur. C'est plus de travail à l'entretien, mais un seul non-requête de jointure comme:
Espère que ça aide.