2010-10-28 2 views
3

Я привык писать свои собственные SQL-запросы, и я пытаюсь привыкнуть ко всему объекту ORM, который кажется таким популярным в наши дни.Как я могу выполнить этот сложный SQL-запрос с помощью Django ORM? (подзапрос с соединением)

Вот запрос:

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 
) 

, где% s представляет собой целое число.

Я использую ORM по умолчанию Django. Какой самый питонический способ сделать это?

Некоторая справочная информация: БД, которую я использую, представляет собой спецификацию GTFS (спецификация Google Transit feed). Этот запрос должен получить список из route, который проходит через конкретный stop, однако информация, связывающая их, находится в таблице trips.

Этот запрос отлично подходит для меня, поэтому единственная причина, по которой я прошу, - это учиться.

Спасибо!

ответ

1

Это, вероятно, будет немного легче, чтобы выяснить, подходящий способ сделать это, если у вас было то, что вы использовали для соответствующего Models.

Я что-то вроде следующего предполагая, на основе спецификации вы упомянули, работая от:

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 

Если это так ... вы должны быть в состоянии сделать что-то вроде

Route.objects.filter(trip__stop__id=my_stop_id) 

, чтобы получить все Route объектов, которые проходят через заданный Stop с первичным ключом id, равным my_stop_id, который я принимаю, является целым числом в соответствии с вашим сообщением.

Прошу прощения, если синтаксис немного выключен, так как мне не нужно было делать отношения «многие ко многим», используя явную дополнительную таблицу. Некоторая корректировка также может потребоваться, если вам нужно (или выбрать) использовать параметр related_name для любых внешних ключей или поля «много-для-много».

+0

Большое спасибо, это очень полезно. У вас есть модели правильно, и я постараюсь выполнить этот запрос в ближайшее время. Еще один вопрос: в чем разница между ForeignKey и ManyToMany? –

+0

'ForeignKeys' предназначены для отношений« один-два-один »и помещаются в« Модель »на стороне« Много ». ManyToManyFields для отношений «многие ко многим»; на самом деле это не так важно, внутренне, из двух связанных с ним моделей, в которые он помещается, поэтому вы обычно помещаете его в ту, где вы, скорее всего, захотите ее отредактировать (например, встроенные формы администратора Django) , Таблица автоматически создается для представления отношения, которое в основном состоит из двух объектов ForeignKey. – desfido

+0

(о, но в этом случае, поскольку есть дополнительные метаданные о взаимоотношениях «многие ко многим», я вместо этого предположил, что вы делаете это вручную, используя «StopTime». Именно поэтому необходимо использовать параметр 'through' для «ManyToManyField». Если вы решили, что дополнительные данные, данные для «StopTime», были посторонними, кроме информации «много-ко-многим», вы могли бы устранить модель «StopTime» и параметр «сквозной». Нормальные соглашения об именах Django то тогда вы называете «ManyToManyField» как «времена» или что-то подобное.) – desfido

1

Исправьте меня, если я ошибаюсь, но я не думаю, что вы можете сделать это с помощью Django ORM обычным способом.

Нет поддержки подзапросов, и при нормальном объединении это будет зависеть от вашей базы данных, если отдельный пользователь может вам помочь. Если вы используете Postgres, чем вы могли бы сделать это с этим патчем: http://code.djangoproject.com/ticket/6422

Запрос будет что-то вроде этого:

Route.objects.filter(stop_time__trips__stop_id=...).distinct('stop_time__route_id') 
Смежные вопросы