Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self join with django ORM

Tags:

django

I have a model:

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)  
    ...

and I want to execute next query:

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

can it be done without hacks using Django ORM? Thx!

like image 985
Senyai Avatar asked Oct 16 '09 14:10

Senyai


2 Answers

select * ... will take more work. If you can trim back the columns you want from the right hand side

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)])

Add additional columns to have available to the select dict.

The additional constraints are put together in a WHERE after the ON (), which your SQL engine may optimize poorly.

like image 200
Chris Dukes Avatar answered Oct 09 '22 13:10

Chris Dukes


I believe Django's ORM doesn't support doing a join on anything that isn't specified as a ForeignKey (at least, last time I looked into it, that was a limitation. They're always adding features though, so maybe it snuck in).

So your options are to either re-structure your tables so you can use proper foreign keys, or just do a raw SQL Query.

I wouldn't consider a raw SQL query a "hack". Django has good documentation on how to do raw SQL Queries.

like image 37
thraxil Avatar answered Oct 09 '22 14:10

thraxil