I have a somewhat nasty query problem, which I have abstracted and
(partially) simplified into the following test case:

----- test.py -----
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker, aliased,
relationship
from sqlalchemy import Column, Integer, ForeignKey, func,
create_engine

Session = scoped_session(sessionmaker())
Base = declarative_base()

class TableA (Base):
    __tablename__ = 'table_a'

    id = Column(Integer, primary_key=True)
    some_key = Column(Integer, nullable=False)

class TableB (Base):
    __tablename__ = 'table_b'

    id = Column(Integer, primary_key=True)
    a_id = Column(Integer, ForeignKey(TableA.id), nullable=False)
    a = relationship(TableA)

class TableC (Base):
    __tablename__ = 'table_c'

    id = Column(Integer, primary_key=True)
    b_id = Column(Integer, ForeignKey(TableB.id), nullable=False)
    b = relationship(TableB)
    group_key = Column(Integer, nullable=False)
    sort_key = Column(Integer, nullable=False)

def make_data():
    a = TableA(some_key=42)
    b1 = TableB(a=a)
    Session.add(TableC(b=b1, group_key=11, sort_key=0))
    Session.add(TableC(b=b1, group_key=11, sort_key=1))
    Session.add(TableC(b=b1, group_key=7, sort_key=0))
    Session.add(TableC(b=b1, group_key=7, sort_key=1))
    b2 = TableB(a=a)
    Session.add(TableC(b=b2, group_key=11, sort_key=2))

def do_query():
    b1 = aliased(TableB)
    c1 = aliased(TableC)
    q = (
        Session.query(TableC.id, TableC.group_key)
        .join(TableC.b, TableB.a)
        .filter(TableA.some_key == 42)
        .filter(TableC.sort_key ==
                Session.query(func.max(c1.sort_key))
                .join(b1)
                .filter(c1.group_key == TableC.group_key)
                .as_scalar())
        )
    print q.all()

e = create_engine('sqlite:///', echo=True)
Session.configure(bind=e)
Base.metadata.create_all(bind=Session.bind)

make_data()
do_query()
----- test.py -----

This returns one row: (5, 11).  I expect it to return two rows, one
for each group_key  -- so it should also return (4, 7).  The emitted
SQL is:

SELECT table_c.id AS table_c_id, table_c.group_key AS
table_c_group_key
FROM table_c JOIN table_b ON table_b.id = table_c.b_id JOIN table_a ON
table_a.id = table_b.a_id
WHERE table_a.some_key = ? AND table_c.sort_key = (SELECT
max(table_c_1.sort_key) AS max_1
FROM table_c, table_c AS table_c_1 JOIN table_b AS table_b_1 ON
table_b_1.id = table_c_1.b_id
WHERE table_c.group_key = table_c_1.group_key)

The problem is in the FROM clause of the subquery -- there is an extra
table_c in there.  If I manually run that query without the first
table_c in there, then I get the correct result.  So the query should
be:


SELECT table_c.id AS table_c_id, table_c.group_key AS
table_c_group_key
FROM table_c JOIN table_b ON table_b.id = table_c.b_id JOIN table_a ON
table_a.id = table_b.a_id
WHERE table_a.some_key = ? AND table_c.sort_key = (SELECT
max(table_c_1.sort_key) AS max_1
FROM table_c AS table_c_1 JOIN table_b AS table_b_1 ON table_b_1.id =
table_c_1.b_id
WHERE table_c.group_key = table_c_1.group_key)

How do I cajole SQLAlchemy into producing this query?

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to [email protected].
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