queries python mysql django django-queryset django-aggregation

python - queries - ¿Utiliza.aggregate() en un valor introducido usando.extra(select={...}) en una consulta de Django?



group by django (2)

Aquí hay un ejemplo del problema y una solución de solución unideal. Toma este modelo de ejemplo:

class Rating(models.Model): RATING_CHOICES = ( (1, ''1''), (2, ''2''), (3, ''3''), (4, ''4''), (5, ''5''), ) rating = models.PositiveIntegerField(choices=RATING_CHOICES) rater = models.ForeignKey(''User'', related_name=''ratings_given'') ratee = models.ForeignKey(''User'', related_name=''ratings_received'')

Esta consulta agregada de ejemplo falla de la misma manera que la suya porque intenta hacer referencia a un valor no de campo creado con .extra() .

User.ratings_received.extra( select={''percent_positive'': ''ratings > 3''} ).aggregate(count=Avg(''positive''))

Una solución alternativa

El valor deseado se puede encontrar directamente utilizando la función de base de datos agregada (Promedio en este caso) dentro de la definición del valor extra:

User.ratings.extra( select={''percent_positive'': ''AVG(rating >= 3)''} )

Esta consulta generará la siguiente consulta SQL:

SELECT (AVG(rating >= 3)) AS `percent_positive`, `ratings_rating`.`id`, `ratings_rating`.`rating`, `ratings_rating`.`rater_id`, `ratings_rating`.`ratee_id` FROM `ratings_rating` WHERE `ratings_rating`.`ratee_id` = 1

A pesar de las columnas innecesarias en esta consulta, aún podemos obtener el valor deseado al aislar el valor percent_positive :

User.ratings.extra( select={''percent_positive'': ''AVG(rating >= 3)''} ).values(''percent_positive'')[0][''percent_positive'']

Estoy tratando de contar el número de veces que un jugador jugó cada semana de esta manera:

player.game_objects.extra( select={''week'': ''WEEK(`games_game`.`date`)''} ).aggregate(count=Count(''week''))

Pero Django se queja de que

FieldError: Cannot resolve keyword ''week'' into field. Choices are: <lists model fields>

Puedo hacerlo en SQL sin formato como este

SELECT WEEK(date) as week, COUNT(WEEK(date)) as count FROM games_game WHERE player_id = 3 GROUP BY week

¿Hay una buena forma de hacerlo sin ejecutar SQL sin formato en Django?


Puede usar una función agregada personalizada para generar su consulta:

WEEK_FUNC = ''STRFTIME("%%%%W", %s)'' # use ''WEEK(%s)'' for mysql class WeekCountAggregate(models.sql.aggregates.Aggregate): is_ordinal = True sql_function = ''WEEK'' # unused sql_template = "COUNT(%s)" % (WEEK_FUNC.replace(''%%'', ''%%%%'') % ''%(field)s'') class WeekCount(models.aggregates.Aggregate): name = ''Week'' def add_to_query(self, query, alias, col, source, is_summary): query.aggregates[alias] = WeekCountAggregate(col, source=source, is_summary=is_summary, **self.extra) >>> game_objects.extra(select={''week'': WEEK_FUNC % ''"games_game"."date"''}).values(''week'').annotate(count=WeekCount(''pk''))

Pero como esta API no está documentada y ya requiere bits de SQL sin procesar, es mejor que utilices una consulta sin formato .