On 5/27/15 2:43 AM, Nathan wrote:
Hi,

I'm trying to convert the following query to sqlalchemy:

|
SELECT cg.id,cg.namecg.status,history.action,history.timestampFROM customergame cgJOIN history ON history.id=(SELECT idFROM history h WHERE cg.id=h.customergame_idORDER BY timestamp DESC LIMIT 1)ORDER BY gamename ASC
|

so the first thing to note, the subquery here is used in an ON expression against the "=" operator. This means we would like it to act like a column, not a set of rows, and is hence a "scalar subquery" (see http://docs.sqlalchemy.org/en/rel_1_0/glossary.html#term-subquery)



Essentially to select the customergame entry and the last entry in the history table for that customer game.

I've a number of ways to try and archive this, however, nothing so seems to work. For example:

|
subq =db.session.query(History.id).filter(Customergame.id==History.customergame_id).order_by(History.timestamp).limit(1).subquery()
|

which means, we don't want to use subquery(). We want to use as_scalar() which has the subquery act like a column. A Core example is here http://docs.sqlalchemy.org/en/rel_1_0/core/tutorial.html#scalar-selects but same idea for ORM.

Another thing to note, the correlation in the FROM clause is a little non-standard (seems to be accepted by current PG/MySQL versions though), but SQLAlchemy doesn't expect this to happen normally so we also have to tell it to correlate that explicitly. Because I could see this part causing problems I had to verify with a test script (which means you get a working version for free!). It is attached.




|

db.session.query(Customergame).join(History,History.id==subq.c.id)
|

Which produces:
|
SELECT customergame.,
FROM customergame JOIN history ON history.id = anon_1.id
|

Which in turn leads to a exception when it executes:
|
ProgrammingError: (ProgrammingError) missing FROM-clause entry for table "anon_1"
|


Has anybody got any ideas of how to achieve this type of query?

Many thanks in advance!
--
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 <mailto:sqlalchemy+unsubscr...@googlegroups.com>. To post to this group, send email to sqlalchemy@googlegroups.com <mailto:sqlalchemy@googlegroups.com>.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

--
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 http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class History(Base):
    __tablename__ = 'history'
    id = Column(Integer, primary_key=True)
    cg_id = Column(ForeignKey('cg.id'))
    data = Column(String(10))


class CG(Base):
    __tablename__ = 'cg'
    id = Column(Integer, primary_key=True)
    data = Column(String(10))

e = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
Base.metadata.create_all(e)

s = Session(e)

subq = s.query(History.id).filter(CG.id == History.cg_id).\
    order_by(History.data.desc()).limit(1).correlate(CG).as_scalar()

q = s.query(CG).join(History, History.id == subq).order_by(CG.data)

print q

q.all()

"""
SELECT cg.id, cg.name cg.status, history.action, history.timestamp
FROM customergame cg
JOIN history ON history.id =
(SELECT id FROM history h WHERE cg.id = h.customergame_id ORDER BY timestamp DESC LIMIT 1)
ORDER BY gamename ASC


SELECT cg.id AS cg_id, cg.data AS cg_data
FROM cg JOIN history ON history.id = (SELECT history.id
FROM history
WHERE cg.id = history.cg_id ORDER BY history.data
 LIMIT %(param_1)s) ORDER BY cg.data


"""

Reply via email to