Django ORM中的自连接

6

我有一个模型:

class Trades(models.Model):  
    userid     = models.PositiveIntegerField(null=True, db_index=True)
    positionid = models.PositiveIntegerField(db_index=True)
    tradeid    = models.PositiveIntegerField(db_index=True)
    orderid    = models.PositiveIntegerField(db_index=True)  
    ...

我想执行下一个查询:

select *
from trades t1
inner join trades t2
ON t2.tradeid = t1.positionid and t1.tradeid = t2.positionid

能否使用Django ORM而不是hack来实现这个功能呢?谢谢!

2个回答

6

选择所有列会需要更多的工作。如果您可以从右侧减少所需的列,那么会更加方便。

table=SomeModel._meta.db_table
join_column_1=SomeModel._meta.get_field('field1').column
join_column_2=SomeModel._meta.get_field('field2').column
join_queryset=SomeModel.objects.filter()
# Force evaluation of query
querystr=join_queryset.query.__str__()
# Add promote=True and nullable=True for left outer join
rh_alias=join_queryset.query.join((table,table,join_column_1,join_column_2))
# Add the second conditional and columns
join_queryset=join_queryset.extra(select=dict(rhs_col1='%s.%s' % (rhs,join_column_2)),
    where=['%s.%s = %s.%s' % (table,join_column_2,rh_alias,join_column_1)])

新增额外的列以便在选择字典中使用。

额外的约束条件将在ON()之后组合成WHERE语句,这可能会导致你的SQL引擎优化不佳。


2
我认为 Django 的 ORM 不支持在任何未指定为 ForeignKey 的内容上进行联接(至少在我上次研究时是这样的限制。不过他们一直在添加功能,所以也许已经加入了)。因此,你的选择要么重新设计你的表格,以便使用适当的外键,要么只能使用原始的 SQL 查询。
我不认为原始的 SQL 查询是“hack”。Django 在如何进行原始 SQL 查询方面有很好的文档。

2
在最近的 Django 版本中,你可以添加一个自连接(self-join)。以下是使用 Django 1.11.7 版本的示例代码:parent = models.ForeignKey('self',on_delete=models.CASCADE,db_column='parent_id',null=True, blank=True) - Keith John Hutchison

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接