Sql Django中具有非外键联接的约束
在我的数据库中,我有一对表(Sql Django中具有非外键联接的约束,sql,django,Sql,Django,在我的数据库中,我有一对表(tableA和tableB),它们都有外键引用tableC中的同一列ID。我能够使用的SQL是 SELECT * FROM tableA INNER JOIN tableB on tableA.ID=tableB.ID WHERE tableB.year=2011 询问 SELECT * FROM tableA INNER JOIN tableB on tableA.ID=tableB.ID AND tableB.year=2011 做了同样的事 在Django中
tableA
和tableB
),它们都有外键引用tableC
中的同一列ID
。我能够使用的SQL是
SELECT *
FROM tableA
INNER JOIN tableB on tableA.ID=tableB.ID
WHERE tableB.year=2011
询问
SELECT *
FROM tableA
INNER JOIN tableB on tableA.ID=tableB.ID AND tableB.year=2011
做了同样的事
在Django中,我试图用代码来实现这一点
subquery=tableB.objects.filter(year=2011).values_list(id, flat=True)
results=tableA.objects.filter(id__in=list(subquery))
正如报告中所建议的那样。我知道这有点不同,因为它只返回
tableA
中的列,但我还是只使用这些列。Django代码似乎很慢,我想部分原因是对tableA
的每一行进行集合成员测试,这非常大。在Django中有没有一种不用原始SQL(如果需要的话,我当然可以使用原始SQL)就可以更快地实现这一点的方法?您的模型似乎不太“Django”友好。您是否使用一对一关系,并且您的表pk是外键?(如果不是,请在问题中张贴您的模式)。Django希望表(模型)主键是唯一的自动递增整数,而不是外键
django明智的做法是:
类表C(models.Model):
name=models.CharField(最大长度=1000)
类别表A(models.Model):
表C=模型。OneToOneField(表C)
类别表B(型号.型号):
表C=模型。OneToOneField(表C)
年份=型号。整型字段()
请注意,所有字段都有一个(隐式)id字段,它是表的主键。现在执行:
TableA.objects.filter(tablec\uuuu tableb\uuuu year\uuuuu exact=2011)
实际上,您可以使用外键作为主键:
类表C(models.Model):
name=models.CharField(最大长度=1000)
类别表A(models.Model):
tablec=models.OneToOneField(tablec,primary\u key=True,db\u column='id')
类别表B(型号.型号):
tablec=models.OneToOneField(tablec,primary\u key=True,db\u column='id')
年份=型号。整型字段()
并执行相同的查询。但是,这可能会在以后给您带来更多的问题(“无保修”)。它的速度很慢,因为它正在创建一个可能类似于
SELECT * FROM TableA WHERE ID IN (SELECT ID FROM TableB WHERE year=2011)
就像@Udi所说的,如果你能通过添加外键来“django”使模型更具规模,你会过得更好。否则,使用RawSQL。这就是它的用途。不要将
子查询
转换为列表。如果您只是这样做:
results=tableA.objects.filter(id__in=subquery)
Django应该足够聪明,可以实际执行一个子查询,而不是两个单独的查询。这可能是一个愚蠢的问题,但究竟是什么-你正在运行Django的最新版本吗?我使用的是Django 1.3,而不是开发版本,如果你问的是这个问题的话。如果你还没有,跳转到irc.freenode.net上的#django频道-那里有很多非常棒的开发人员-将url传递给他们到这个页面。我忘了提到,我使用的是MySQL数据库,我链接到的文档页面说MySQL没有很好地优化嵌套查询,使用两个查询会更快。谢谢你的帮助。我会这样做,但我的模型实际上来自其他来源的数据,我只是使用Django作为该数据的接口。另外,如果不进行非规范化,我想不出任何方法可以将表中的关系转换为一对一关系,我不希望这样做。我相信您仍然可以使用一对多来完成上述操作,并避免使用原始sql。在某些情况下,跨越三个表的外键-外键联接可能比使用子查询更快。