python - SQLAlchemy convert outer join ORM query to Core -
i'm having problems sqlalchemy's select_from statement when using core component. try construct outer join query looks like:
query = select([b1.c.id, b1.c.num, n1.c.name, n1.c.num, ...] ).where(and_( ... conditions ... ) ).select_from( ???.outerjoin( n1, and_( ... conditions ... ) ).select_from(... more outer joins similar above ...) according docs, structure should this:
table1 = table('t1', column('a')) table2 = table('t2', column('b')) s = select([table1.c.a]).\ select_from( table1.join(table2, table1.c.a==table2.c.b) ) my problem don't have table1 object in case, select ... part consists of columns , not single table (see question marks in query). i've tried using n1.outerjoin(n1..., caused exception (exception: (programmingerror) table name "n1" specified more once).
the above snippet derived working session-based (orm) query, try convert (with limited success).
b = table('b', metadata, column('id', integer, sequence('seq_b_id')), column('num', integer, nullable=false), column('active', boolean, default=false), ) n = table('n', metadata, column('b_id', integer, nullable=false), column('num', integer, nullable=false), column('active', boolean, default=false), ) p = table('p', metadata, column('b_id', integer, nullable=false), column('num', integer, nullable=false), column('active', boolean, default=false), ) n1 = aliased(n, name='n1') n2 = aliased(n, name='n2') b1 = aliased(b, name='b1') b2 = aliased(b, name='b2') p1 = aliased(p, name='p1') p2 = aliased(p, name='p2') result = sess.query(b1.id, b1.num, n1.c.name, n1.c.num, p1.par, p1.num).filter( b1.active==false, b1.num==sess.query(func.max(b2.num)).filter( b2.id==b1.id ) ).outerjoin( n1, and_( n1.c.b_id==b1.id, n1.c.num<=num, n1.c.active==false, n1.c.num==sess.query(func.max(n2.num)).filter( n2.id==n1.c.id ) ) ).outerjoin( p1, and_( p1.b_id==b1.id, p1.num<=num, p1.active==false, p1.num==sess.query(func.max(p2.num)).filter( p2.id==p1.id ) ) ).order_by(b1.id) how go converting orm query plain core query? update:
i able narrow down problem. seems combination of 2 select_from calls causes 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) r in result.fetchall(): print r the above code causes following exception:
programmingerror: (programmingerror) table name "customer1" specified more once 'select customer1.id, customer.name, order1.id, order1.order_num, address1.id, address1.city \nfrom customer, customer customer1 left outer join "order" order1 on order1.customer_id = customer1.id, customer customer1 left outer join address address1 on customer1.id = address1.customer_id' {} if bit more experienced in using sqlalchemy, bug...
i managed solved problem. instead of cascading select_from, additional joins need chained actual join. above query 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 ) ) )
Comments
Post a Comment