Sqlalchemy: subquery in FROM must have an alias
如何构造此sqlalchemy查询,以使其执行正确的操作?
我已经给出了所有我能想到的别名,但是我仍然得到:
1 2 | ProgrammingError: (psycopg2.ProgrammingError) subquery in FROM must have an alias LINE 4: FROM (SELECT foo.id AS foo_id, foo.version AS ... |
此外,正如IMSoP所指出的那样,它似乎正在尝试将其转换为交叉联接,但我只希望它通过同一查询的子查询对同一张表进行联接。
这是sqlalchemy:
(注意:我已经将其重写为一个尽可能完整的独立文件,可以从python shell运行)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | from sqlalchemy import create_engine, func, select from sqlalchemy import Column, BigInteger, DateTime, Integer, String, SmallInteger from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker engine = create_engine('postgresql://postgres:#######@localhost:5435/foo1234') session = sessionmaker() session.configure(bind=engine) session = session() Base = declarative_base() class Foo(Base): __tablename__ = 'foo' __table_args__ = {'schema': 'public'} id = Column('id', BigInteger, primary_key=True) time = Column('time', DateTime(timezone=True)) version = Column('version', String) revision = Column('revision', SmallInteger) foo_max_time_q = select([ func.max(Foo.time).label('foo_max_time'), Foo.id.label('foo_id') ]).group_by(Foo.id ).alias('foo_max_time_q') foo_q = select([ Foo.id.label('foo_id'), Foo.version.label('foo_version'), Foo.revision.label('foo_revision'), foo_max_time_q.c.foo_max_time.label('foo_max_time') ]).join(foo_max_time_q, foo_max_time_q.c.foo_id == Foo.id ).alias('foo_q') thing = session.query(foo_q).all() print thing |
生成的sql:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | SELECT foo_id AS foo_id, foo_version AS foo_version, foo_revision AS foo_revision, foo_max_time AS foo_max_time, foo_max_time_q.foo_max_time AS foo_max_time_q_foo_max_time, foo_max_time_q.foo_id AS foo_max_time_q_foo_id FROM (SELECT id AS foo_id, version AS foo_version, revision AS foo_revision, foo_max_time_q.foo_max_time AS foo_max_time FROM (SELECT max(time) AS foo_max_time, id AS foo_id GROUP BY id ) AS foo_max_time_q) JOIN (SELECT max(time) AS foo_max_time, id AS foo_id GROUP BY id ) AS foo_max_time_q ON foo_max_time_q.foo_id = id |
这是玩具桌:
1 2 3 4 5 6 | CREATE TABLE foo ( id bigint , time timestamp with time zone, version character varying(32), revision smallint ); |
我期望获得的SQL(期望的SQL)将是这样的:
1 2 3 4 5 6 7 8 9 | SELECT foo.id AS foo_id, foo.version AS foo_version, foo.revision AS foo_revision, foo_max_time_q.foo_max_time AS foo_max_time FROM foo JOIN (SELECT max(time) AS foo_max_time, id AS foo_id GROUP BY id ) AS foo_max_time_q ON foo_max_time_q.foo_id = foo.id |
最后的注释:
我希望尽可能使用select()而不是session.query()获得答案。谢谢
您快到了。进行"可选"子查询,然后通过
将其与主查询联接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | foo_max_time_q = select([func.max(Foo.time).label('foo_max_time'), Foo.id.label('foo_id') ]).group_by(Foo.id ).alias("foo_max_time_q") foo_q = session.query( Foo.id.label('foo_id'), Foo.version.label('foo_version'), Foo.revision.label('foo_revision'), foo_max_time_q.c.foo_max_time.label('foo_max_time') ).join(foo_max_time_q, foo_max_time_q.c.foo_id == Foo.id) print(foo_q.__str__()) |
打印(手动美化):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | SELECT foo.id AS foo_id, foo.version AS foo_version, foo.revision AS foo_revision, foo_max_time_q.foo_max_time AS foo_max_time FROM foo JOIN (SELECT max(foo.time) AS foo_max_time, foo.id AS foo_id FROM foo GROUP BY foo.id) AS foo_max_time_q ON foo_max_time_q.foo_id = foo.id |
完整的工作代码在此要点中。