I try to code the equivalent Django query from this SQL query, but I'm stuck.
Any help is welcome.
I receive a race id and from this race I want to do some statistics : nb_race = the number of races from a Horse before the race given, best_chrono = best time from a Horse before the race given.
SELECT *, (SELECT count(run.id)
FROM runner run
INNER JOIN race
ON run.race_id = race.id
WHERE run.horse_id = r.horse_id
AND race.datetime_start < rc.datetime_start
) AS nb_race,
(SELECT min(run.chrono)
FROM runner run
INNER JOIN race
ON run.race_id = race.id
WHERE run.horse_id = r.horse_id
AND race.datetime_start < rc.datetime_start
) AS best_time
FROM runner r, race rc
WHERE r.race_id = rc.id
AND rc.id = 7890
Django Models:
class Horse(models.Model):
id = AutoField(primary_key=True)
name = models.CharField(max_length=255, blank=True, null=True, default=None)
class Race(models.Model):
id = AutoField(primary_key=True)
datetime_start = models.DateTimeField(blank=True, null=True, default=None)
name = models.CharField(max_length=255, blank=True, null=True, default=None)
class Runner(models.Model):
id = AutoField(primary_key=True)
horse = models.ForeignKey(Horse, on_delete=models.PROTECT)
race = models.ForeignKey(Race, on_delete=models.PROTECT)
chrono = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, default=None)
Subquery expression can be used to compile an additional queryset as subquery that depends on the main queryset and execute them together as one SQL.
Some tricks used here are described in the linked docs:
.values(...)to one field: only the aggregated value.annotate()is used in the subquery (not.aggregate()). That adds aGROUP BY race.horse_id, but is is not a problem becase there is alsoWHERE race.horse_id = ...and the "group by" will be finally ignored by an SQL optimizer in a modern database backend.It is compiled to a query equivalent to the SQL in the example. Check the SQL:
A marginal difference is that a subquery uses some internal aliases like U0 and U1.