¿Cómo puedo hacer esta consulta SQL compleja usando Django ORM? (Sub-consulta con una combinación)
Pregunta
Estoy acostumbrado a escribir mis propias consultas SQL y estoy tratando de acostumbrarse a todo el asunto ORM que parece ser tan popular hoy en día.
Aquí está la consulta:
SELECT * FROM routes WHERE route_id IN (
SELECT DISTINCT t.route_id FROM stop_times AS st
LEFT JOIN trips AS t ON st.trip_id=t.trip_id
WHERE stop_id = %s
)
donde% s es un número entero.
Estoy usando ORM de Django por defecto. ¿Cuál es la forma más Pythonic hacer esto?
Algunos información de fondo: La base de datos que estoy usando es de unos GTFS (especificación de feeds de Google Transit). Esta consulta se supone que para obtener una lista de todos los route
que pasa por un stop
particular, sin embargo la información de conexión de estos es en la tabla trips
.
Esta consulta funciona bien para mí, por lo que la única razón por la que estoy pidiendo es aprender.
Gracias!
Solución
Probablemente sería un poco más fácil de averiguar la manera apropiada de hacer esto si tuviera lo que estaba utilizando para la Models
relevante.
Estoy asumiendo algo como lo siguiente, basada en la especificación mencionaste trabajo en:
class Route(models.Model):
#bunch of stuff
pass
class Stop(models.Model):
#bunch of stuff
stop_times = models.ManyToManyField(through=StopTime)
class StopTime(models.Model):
trip = models.ForeignKey(Trip)
stop = models.ForeignKey(Stop)
# bunch of additional meta about this M2M table
pass
class Trip(models.Model):
route = models.ForeignKey(Route)
# bunch of stuff
Si ese es el caso ... usted debe ser capaz de hacer algo como
Route.objects.filter(trip__stop__id=my_stop_id)
para conseguir todos los objetos Route
que pasan por un determinado Stop
con un id
clave principal iguales a my_stop_id
, que estoy asumiendo que es un entero como por su puesto.
Me disculpo si la sintaxis es un poco apagado, ya que no he necesitado hacer muchos-a-muchos relaciones usando una mesa extra explícita. Algunos ajuste también puede ser necesaria si usted tiene (o elija a) utilizar el parámetro para cualquier related_name
las claves externas o el campo de muchos a muchos.
Otros consejos
corrígeme si estoy equivocado, pero no creo que se puede hacer eso con Django ORM de una manera normal.
No hay soporte subconsulta y con un normal de unirse a ella dependería de su base de datos si una clara podría ayudarle. Si está utilizando Postgres de lo que podría hacerlo con este parche: http://code.djangoproject.com/ticket / 6422
La consulta sería algo como esto:
Route.objects.filter(stop_time__trips__stop_id=...).distinct('stop_time__route_id')