如何使用Django ORM执行这个复杂的SQL查询?(带连接的子查询)
我习惯自己写SQL查询,现在想适应一下现在很流行的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 是一个整数。
我在用Django的默认ORM。请问用Python的方式怎么做这个比较好呢?
一些背景信息:我使用的数据库来自GTFS(谷歌交通信息规范)。这个查询是为了获取经过特定 stop
的每条 route
,但这些信息是在 trips
表里。
这个查询对我来说运行得很好,所以我问这个问题只是想学习一下。
谢谢!
2 个回答
1
如果我说错了请纠正我,但我觉得用Django的ORM(对象关系映射)是无法以正常方式做到这一点的。
它不支持子查询,使用普通的连接查询的话,能否使用distinct(去重)要看你的数据库。如果你使用的是Postgres数据库,那么可以通过这个补丁来实现:http://code.djangoproject.com/ticket/6422
查询的写法大概是这样的:
Route.objects.filter(stop_time__trips__stop_id=...).distinct('stop_time__route_id')
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)
这样就能获取到所有经过某个特定 Stop
的 Route
对象,前提是这个 Stop
的主键 id
等于 my_stop_id
,我假设这个值是个整数,正如你帖子里提到的。
如果语法有点不对,我先说声抱歉,因为我之前没怎么用过需要额外表的多对多关系。如果你需要(或者选择)为任何外键或多对多字段使用 related_name
参数,可能还需要做一些调整。