On Mon, Feb 12, 2018 at 11:38 AM, Christophe Biocca <christophe.bio...@gmail.com> wrote: > Right, I can unpack the relationship between A and B into column expressions > manually, but this will break for `secondaryjoin` relationships. > I guess I can unpack those manually as well, by introducing the secondary > table expression when needed. I will try that. >
you need to show me a mapping and SQL you want, then I can show you that. > On 12 February 2018 at 11:24, Mike Bayer <mike...@zzzcomputing.com> wrote: >> >> On Sat, Feb 10, 2018 at 6:17 PM, Christophe Biocca >> <christophe.bio...@gmail.com> wrote: >> > Let's say I have 2 models, A and B, with relationships A.bs >> > (haslist=True) >> > and B.a (haslist=False) >> > >> > Doing a semi join is trivial: >> > >> > session.query(A).filter(A.bs.any(SomeConditionOnB)) >> > session.query(B).filter(B.a.has(SomeConditionOnA)) >> > >> > Doing a regular join is also trivial: >> > >> > session.query(A).join(A.bs).filter(SomeConditionOnB) >> > session.query(B).filter(B.a).filter(SomeConditionOnA) >> > >> > I'd like to generate the following statement: >> > >> > SELECT * FROM a WHERE (EXISTS >> > ( >> > SELECT 1 FROM b WHERE SomeConditionOnB AND b.a_id = a.id >> > UNION SELECT 1 FROM b WHERE SomeOtherConditionOnB AND b.a_id = >> > a.id >> > ) >> > ) >> > >> > Because in my case `WHERE EXISTS( foo UNION bar )` is much, much faster >> > than >> > `WHERE EXISTS( foo ) OR EXISTS( bar )`. >> > >> > I've figured out how do do it as a regular join (with `aliased(B, >> > b1.union(b2))`) but that won't work (it'll return some rows repeatedly >> > due >> > to JOIN's behaviour vs the semijoin of EXISTS). >> > >> > `has` and `any` both take a criterion object (?) which means giving it >> > an >> > aliased object won't work either. >> > >> > I've tried directly using `A.b.expression` and ClauseAdapter based on my >> > perusing of the source code, but it won't work with tables with >> > secondary >> > joins and the like. >> >> there's no joins in the statement you describe, you can get that >> close-to-identical SQL using union() and exists() normally, full >> example: >> >> from sqlalchemy import * >> from sqlalchemy.orm import * >> from sqlalchemy.ext.declarative import declarative_base >> from sqlalchemy.ext.declarative import declared_attr >> >> Base = declarative_base() >> >> >> class A(Base): >> __tablename__ = 'a' >> id = Column(Integer, primary_key=True) >> bs = relationship("B") >> >> >> class B(Base): >> __tablename__ = 'b' >> id = Column(Integer, primary_key=True) >> a_id = Column(ForeignKey('a.id')) >> >> session = Session() >> >> >> """ >> I'd like to generate the following statement: >> >> SELECT * FROM a WHERE (EXISTS >> ( >> SELECT 1 FROM b WHERE SomeConditionOnB AND b.a_id = a.id >> UNION SELECT 1 FROM b WHERE SomeOtherConditionOnB AND b.a_id = >> a.id >> ) >> ) >> """ >> >> q = session.query(A).filter( >> session.query(B.id).filter(B.id > 5).filter(B.a_id == >> A.id).correlate(A). >> union( >> session.query(B.id).filter(B.id < 10).filter(B.a_id == A.id). >> correlate(A) >> ).exists() >> ) >> >> print(q) >> >> >> """ >> SELECT a.id AS a_id FROM a WHERE EXISTS >> ( >> SELECT 1 FROM ( >> SELECT b.id AS b_id FROM b WHERE b.id > :id_1 AND b.a_id = >> a.id >> UNION SELECT b.id AS b_id FROM b WHERE b.id < :id_2 AND >> b.a_id = a.id >> ) AS anon_1 >> ) >> >> """ >> >> >> >> >> >> >> > >> > -- >> > SQLAlchemy - >> > The Python SQL Toolkit and Object Relational Mapper >> > >> > http://www.sqlalchemy.org/ >> > >> > To post example code, please provide an MCVE: Minimal, Complete, and >> > Verifiable Example. See http://stackoverflow.com/help/mcve for a full >> > description. >> > --- >> > You received this message because you are subscribed to the Google >> > Groups >> > "sqlalchemy" group. >> > To unsubscribe from this group and stop receiving emails from it, send >> > an >> > email to sqlalchemy+unsubscr...@googlegroups.com. >> > To post to this group, send email to sqlalchemy@googlegroups.com. >> > Visit this group at https://groups.google.com/group/sqlalchemy. >> > For more options, visit https://groups.google.com/d/optout. >> >> -- >> SQLAlchemy - >> The Python SQL Toolkit and Object Relational Mapper >> >> http://www.sqlalchemy.org/ >> >> To post example code, please provide an MCVE: Minimal, Complete, and >> Verifiable Example. See http://stackoverflow.com/help/mcve for a full >> description. >> --- >> You received this message because you are subscribed to a topic in the >> Google Groups "sqlalchemy" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/sqlalchemy/s3YKpfv3j1Y/unsubscribe. >> To unsubscribe from this group and all its topics, send an email to >> sqlalchemy+unsubscr...@googlegroups.com. >> To post to this group, send email to sqlalchemy@googlegroups.com. >> Visit this group at https://groups.google.com/group/sqlalchemy. >> For more options, visit https://groups.google.com/d/optout. > > > -- > SQLAlchemy - > The Python SQL Toolkit and Object Relational Mapper > > http://www.sqlalchemy.org/ > > To post example code, please provide an MCVE: Minimal, Complete, and > Verifiable Example. See http://stackoverflow.com/help/mcve for a full > description. > --- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at https://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.