Michael Bayer wrote:
> but what happens if i say:
> 
> q.select(or_(User.c.orders.items.item_name == 'item#4',  
> User.c.orders.items.item_name == 'item #5'))
> 
> if we naively convert c.orders.items.item_name=='item #4' into  
> "user.user_id=orders.user_id and orders.order_id=items.order_id and  
> items.item_name='item #4", then the other clause for item #5  
> generates into the same thing and you get an inefficient query.  i  
> wonder also if some expressions above dont work correctly if the join  
> conditions are repeated like that.
> 
> its still better to say:
> 
>       q.select(or_(Item.c.item_name == 'item#4', Item.c.item_name == 'item  
> #5'), from_obj=[c.orders.items])
> 
> isnt it ?  (User.c.orders.items would be a synonym for query.join_via 
> ('orders', 'items'))
> 

Ok, here are some more thoughts about how this might work.

This query:

q.select(or_(
    c.orders.items.item_name == 'item#4',
    c.orders.items.item_name == 'item #5'
))


Should generate something similar to this SQL:

SELECT ...
FROM users u
    INNER JOIN orders o
        ON u.user_id = o.user_id
    INNER JOIN items i
        ON o.order_id = i.order_id
WHERE i.item_name = 'item#4'
   OR i.item_name = 'item #5'


For the given clause, each occurrence of User.c.orders.items is combined into a 
single join path from users to items, and every occurrence of 'item_name' uses 
the same table alias 'i'. Is that too simplistic? Here are a few more examples:


q.select(and_(
    c.orders.order_total > 50,
    or_(
        c.orders.items.item_name == 'item #4',
        c.orders.items.item_name == 'item #5',
    )
))

SELECT ...
FROM users u
    INNER JOIN orders o
        ON u.user_id = o.user_id
    INNER JOIN items i
        ON o.order_id = i.order_id
WHERE o.order_total > 50 AND
(
    i.item_name = 'item#4' OR
    i.item_name = 'item #5'
)

# -------------------

q.select(or_(
    c.orders.items.item_name == 'item #4',
    and_(
        c.orders.order_total > 50,
        c.orders.items.item_name == 'item #5',
    )
))

SELECT ...
FROM users u
    INNER JOIN orders o
        ON u.user_id = o.user_id
    INNER JOIN items i
        ON o.order_id = i.order_id
WHERE i.item_name = 'item#4' OR
(
    o.order_total > 50 AND
    i.item_name = 'item #5'
)


Notice how the join path for Users.c.orders is superimposed on the join path 
for Users.c.orders.items. It should be possible to use the alias function to 
force separate joins like this:

q.select(and_(
    c.orders.alias('ox').order_total > 50,
    or_(
        c.orders.alias('o').items.item_name == 'item #4',
        c.orders.alias('o').items.item_name == 'item #5',
    )
))

SELECT ...
FROM users u
    INNER JOIN orders ox
        ON u.user_id = ox.user_id
    INNER JOIN orders o
        ON u.user_id = o.user_id
    INNER JOIN items i
        ON o.order_id = i.order_id
WHERE ox.order_total > 50 AND
(
    i.item_name = 'item#4' OR
    i.item_name = 'item #5'
)

ASIDE: One thing we might want to change is the 'alias' function. Since the 
'orders' table may have a column named 'alias', it might be better to make it a 
stand-alone function like this:

alias(c.orders, 'ox')


~ Daniel


--~--~---------~--~----~------------~-------~--~----~
 You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to