简体   繁体   中英

SQLAlchemy convert outer join ORM query to Core

I'm having problems with SQLAlchemy's select_from statement when using the core component. I try to construct an outer join query which currently looks like:

 
 
 
 
  
  
  query = select([b1.c.id, b1.c.num, n1.c.name, n1.c.num, ...] ).where(and_( ... some conditions ... ) ).select_from( ???.outerjoin( n1, and_( ... some conditions ... ) ).select_from(... more outer joins similar to the above ...)
 
 
  

According to the docs, the structure should look like this:

 
 
 
 
  
  
  table1 = table('t1', column('a')) table2 = table('t2', column('b')) s = select([table1.ca]).\\ select_from( table1.join(table2, table1.ca==table2.cb) )
 
 
  

My problem is that I don't have a table1 object in this case, as the select ... part consists of columns and not a single table (see question marks in my query). I've tried using n1.outerjoin(n1... , but that caused an exception ( Exception: (ProgrammingError) table name "n1" specified more than once ).

The above snippet is derived from a working session-based (ORM) query, which I try to convert (with limited success).

ProgrammingError: (ProgrammingError) table name "customer1" specified more than once
 'SELECT customer1.id, customer.name, order1.id, order1.order_num, address1.id, address1.city \nFROM customer, customer AS customer1 LEFT OUTER JOIN "order" AS order1 ON order1.customer_id = customer1.id, customer AS customer1 LEFT OUTER JOIN address AS address1 ON customer1.id = address1.customer_id' {}

How do I go about converting this ORM query into a plain Core query? Update:

I was able to narrow down the problem. It seems that a combination of two select_from calls causes the problem.

 customer = Table('customer', metadata, Column('id', Integer), Column('name', String(50)), ) order = Table('order', metadata, Column('id', Integer), Column('customer_id', Integer), Column('order_num', Integer), ) address = Table('address', metadata, Column('id', Integer), Column('customer_id', Integer), Column('city', String(50)), ) metadata.create_all(db) customer1 = aliased(customer, name='customer1') order1 = aliased(order, name='order1') address1 = aliased(address, name='address1') columns = [ customer1.c.id, customer.c.name, order1.c.id, order1.c.order_num, address1.c.id, address1.c.city ] query = select(columns) query = query.select_from( customer1.outerjoin( order1, and_( order1.c.customer_id==customer1.c.id, ) ) ) query = query.select_from( customer1.outerjoin( address1, and_( customer1.c.id==address1.c.customer_id ) ) ) result = connection.execute(query) for r in result.fetchall(): print r 

The above code causes the following exception:

 ProgrammingError: (ProgrammingError) table name "customer1" specified more than once 'SELECT customer1.id, customer.name, order1.id, order1.order_num, address1.id, address1.city \\nFROM customer, customer AS customer1 LEFT OUTER JOIN "order" AS order1 ON order1.customer_id = customer1.id, customer AS customer1 LEFT OUTER JOIN address AS address1 ON customer1.id = address1.customer_id' {} 

If I was a bit more experienced in using SQLAlchemy, I would say this could be a bug...

I finally managed to solved the problem. Instead of cascading select_from , additional joins need to be chained to the actual join. The above query would read:

query = select(columns)
query = query.select_from(
    customer1.outerjoin(
        order1,
        and_(
            order1.c.customer_id==customer1.c.id,
        )
    ).outerjoin(
        address1,
        and_(
            customer1.c.id==address1.c.customer_id
        )
    )
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM