Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

172
Vistas
Anotación de subconsulta resumida con un filtro por referencia externa ForeignKey

Intento codificar la consulta Django equivalente a partir de esta consulta SQL, pero estoy atascado. Cualquier ayuda es bienvenida. Recibo una id de carrera y de esta carrera quiero hacer algunas estadísticas: nb_race = el número de carreras de un Caballo antes de la carrera dada, best_chrono = mejor tiempo de un Caballo antes de la carrera dada.

 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

Modelos Django:

 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)
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

La expresión de subconsulta se puede usar para compilar un conjunto de consulta adicional como una subconsulta que depende del conjunto de consulta principal y ejecutarlos juntos como un solo SQL.

 from django.db.models import OuterRef, Subquery, Count, Min, F # prepare a repeated expression about previous runners, but don't execute it yet prev_run = ( Runner.objects .filter( horse=OuterRef('horse'), race__datetime_start__lt=OuterRef('race__datetime_start')) .values('horse') ) queryset = ( Runner.objects .values('id', 'horse_id', 'race_id', 'chrono', 'race__name', 'race__datetime_start') .annotate( nb_race=Subquery(prev_run.annotate(nb_race=Count('id')).values('nb_race')), best_time=Subquery(prev_run.annotate(best_time=Min('chrono')).values('best_time')) ) )

Algunos trucos utilizados aquí se describen en los documentos vinculados:

  • Los campos de salida de la Subconsulta deben estar restringidos por .values(...) a un campo: solo el valor agregado
  • Una subconsulta debe ser un conjunto de consultas (que se evalúa de forma diferida y combinada), no un valor (que se evaluaría inmediatamente y fallaría). Por lo tanto .annotate() se usa en la subconsulta (no .aggregate() ). Eso agrega un GROUP BY race.horse_id , pero no es un problema porque también hay WHERE race.horse_id = ... y un optimizador de SQL finalmente ignorará el "group by" en un backend de base de datos moderno.

Se compila en una consulta equivalente al SQL del ejemplo. Compruebe el SQL:

 >>> print(str(queryset.query)) SELECT ..., (SELECT COUNT(U0.id) FROM runner U0 INNER JOIN race U1 ON (U0.race_id = U1.id) WHERE (U0.horse_id = runner.horse_id AND U1.datetime_start < race.datetime_start) GROUP BY U0.horse_id ) AS nb_race, ... FROM runner INNER JOIN race ON (runner.race_id = race.id)

Una diferencia marginal es que una subconsulta utiliza algunos alias internos como U0 y U1.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda