Como posso fazer essa consulta SQL complexa usando o Django ORM? (Sub-quaria com uma junção)

StackOverflow https://stackoverflow.com/questions/4039711

Pergunta

Estou acostumado a escrever minhas próprias consultas SQL e estou tentando me acostumar com toda a coisa do ORM que parece ser tão popular hoje em dia.

Aqui está a 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
)

onde %s é um número inteiro.

Estou usando o ORM padrão do Django. Qual é a maneira mais pitônica de fazer isso?

Algumas informações em segundo plano: o banco de dados que estou usando é de um GTFS (Google Transit Feed Specification). Esta consulta deve obter uma lista de cada route isso passa por um determinado stop, no entanto, as informações que ligam isso estão no trips tabela.

Essa consulta funciona muito bem para mim, então a única razão pela qual estou pedindo é aprender.

Obrigado!

Foi útil?

Solução

Provavelmente seria um pouco mais fácil descobrir a maneira apropriada de fazer isso se você tivesse o que estava usando para o relevante Models.

Estou assumindo algo como o seguinte, com base nas especificações que você mencionou trabalhando:

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

Se for esse o caso ... você deve ser capaz de fazer algo como

Route.objects.filter(trip__stop__id=my_stop_id)

para conseguir tudo Route objetos que passam por um dado Stop com uma chave primária id igual a my_stop_id, que estou assumindo que é um número inteiro de acordo com sua postagem.

Peço desculpas se a sintaxe estiver um pouco fora, pois não precisava fazer relacionamentos muitos para muitos usando uma tabela extra explícita. Alguns ajustes também podem ser necessários se você precisar (ou optar por) usar o related_name Parâmetro para qualquer tecla estrangeira ou para muitos para muitos.

Outras dicas

Corrija -me se eu estiver errado, mas acho que você não pode fazer isso com o Django Orm de maneira normal.

Não há suporte de subconsulta e, com uma junção normal, dependeria do seu banco de dados se um distinto pudesse ajudá -lo. Se você estiver usando o PostGres, poderia fazê -lo com este patch: http://code.djangoproject.com/ticket/6422

A consulta seria algo assim:

Route.objects.filter(stop_time__trips__stop_id=...).distinct('stop_time__route_id')
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top