7
votes

Django Requêtes agrégées avec expressions

J'ai un modèle XYZ et j'ai besoin d'obtenir la valeur max pour les champs A, B et Expression X / Y pour un requérant donné.

Cela fonctionne magnifiquement pour les champs. Quelque chose comme: p> xxx pré>

Cependant, je ne trouve pas un moyen de le faire pour les expressions. Essayer quelque chose comme: p> xxx pré>

donne une erreur: p> xxx pré>

essayer quelque chose comme: p>

XYZ.all().extra(select={'z':'MAX(x/y)'})[0].z


1 commentaires

Vous êtes peut-être intéressé de savoir que la possibilité d'utiliser f () les objets des agrégats est Une partie de la prochaine version de Django 1.8 .


4 Réponses :


-3
votes

Je pense que vous devez obtenir les valeurs maximales séparément xxx

puis diviser les deux champs xxx


1 commentaires

Cela n'a aucun sens. Même s'il renvoie la ligne avec la paire max x et Y, ce n'est pas nécessairement le max X / Y. Par exemple, la rangée max (x) / max (y) est 69/16 = 4, tandis que max (x / y) est 8/1 = 8



6
votes

dans SQL, ce que vous voulez est en réalité xxx pré>

donc dans django orm: p> xxx pré>

la version p>

XYZ.all().extra(select={'z':'MAX(x/y)'})[0].z


2 commentaires

Droite, mais l'intention est d'obtenir la valeur max elle-même, comme le retour de xyz.all (). Agrégat (Max ('a')), pas l'instance le contenant. La version avec extra-sélection est la plus proche de celle-ci. Ne pas renvoyer la bonne instance est un effet secondaire déroutant, mais il renvoie la bonne valeur. Comme je l'ai dit dans le message d'ouverture, je suis au courant des solutions avec des commandes supplémentaires et des commandes, mais elles ne sont pas acceptables car elles nécessitent une sorte de table, pas une seule passe. Il n'a pas beaucoup de sens pour Django de soutenir Max agrégés avec des champs uniques mais pas des expressions.


@pjwerneck La raison de l'effet secondaire confus que vous avez appelé, est décrit dans le dernier paragraphe de ma réponse. Si vous voulez seulement une valeur maximale, xyz.object.extra (SELECT = {'Z': 'Max (x / y)'}) [0] .z suffit, il n'y a pas de commande_by. Ou même directement cursor.execute ('Sélectionnez max (x / y) de xyz') . Je suis d'accord avec vous que Django ne fournit pas d'agrégats avec des expressions, car il pourrait être considérablement plus difficile que de soutenir l'OMI sur le terrain unique.



3
votes

Votre exemple qui utilise f () Les objets doivent fonctionner correctement depuis Django 1.8: xxx

Il y a un extrait qui démontre l'agrégation avec SUM () < / code> et f () objets dans Feuille de triche d'agrégation Django : xxx


1 commentaires

Bon à savoir. Merci!



0
votes

Pour les versions inférieures à 1.8, vous pouvez obtenir la même chose de cette manière (non-documenté).

Book.objects.all().aggregate(price_per_page=Sum('price_per_page', 
                                                field='book_price/book_pages'))


0 commentaires