Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering with joined tables

I'm trying to get some query performance improved, but the generated query does not look the way I expect it to.

The results are retrieved using:

query = session.query(SomeModel).
        options(joinedload_all('foo.bar')).
        options(joinedload_all('foo.baz')).
        options(joinedload('quux.other'))

What I want to do is filter on the table joined via 'first', but this way doesn't work:

query = query.filter(FooModel.address == '1.2.3.4')

It results in a clause like this attached to the query:

WHERE foos.address = '1.2.3.4'

Which doesn't do the filtering in a proper way, since the generated joins attach tables foos_1 and foos_2. If I try that query manually but change the filtering clause to:

WHERE foos_1.address = '1.2.3.4' AND foos_2.address = '1.2.3.4'

It works fine. The question is of course - how can I achieve this with sqlalchemy itself?

like image 355
viraptor Avatar asked Mar 22 '12 11:03

viraptor


People also ask

Can you filter on a join in SQL?

In an SQL query, data can be filtered in the WHERE clause or the ON clause of a join.

Should I filter before join SQL?

Normally, filtering is processed in the WHERE clause once the two tables have already been joined. It's possible, though that you might want to filter one or both of the tables before joining them. For example, you only want to create matches between the tables under certain circumstances.

Can you filter in a left join?

When doing a left join in SQL any filtering of the table after the join will turn it into an inner join. However there are some easy ways to do the filtering first. Suppose you've got some tables related to a website. The pages table describes the different pages on the site.

What's better from a performance point of view filtering data first and then joining it with other sources or joining it first and then filtering?

What's better from a performance point of view: Filtering data first and then joining it with other sources, or joining it first and then filtering? It's better to filter data first and then join it with other sources.


1 Answers

If you want to filter on joins, you use join():

session.query(SomeModel).join(SomeModel.foos).filter(Foo.something=='bar')

joinedload() and joinedload_all() are used only as a means to load related collections in one pass, not used for filtering/ordering!. Please read:

http://docs.sqlalchemy.org/en/latest/orm/tutorial.html#joined-load - the note on "joinedload() is not a replacement for join()", as well as :

http://docs.sqlalchemy.org/en/latest/orm/loading.html#the-zen-of-eager-loading

like image 93
zzzeek Avatar answered Nov 01 '22 17:11

zzzeek