Как я могу структурировать этот запрос sqlalchemy так, чтобы он поступал правильно?Sqlalchemy: подзапрос в FROM должен иметь псевдоним
Я дал все, что я могу думать псевдоним, но я все еще получаю:
ProgrammingError: (psycopg2.ProgrammingError) subquery in FROM must have an alias
LINE 4: FROM (SELECT foo.id AS foo_id, foo.version AS ...
Кроме того, как IMSoP отметил, что, кажется, пытается превратить его в крест присоединиться, но я просто хочу, чтобы он присоединился к таблице с группой по подзапросу в той же таблице.
Вот SQLAlchemy:
(Примечание: Я переписать его, чтобы быть автономный файл, который является как можно более полным и может быть запущен из питона оболочки)
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:
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
и вот т ой таблице:
CREATE TABLE foo (
id bigint ,
time timestamp with time zone,
version character varying(32),
revision smallint
);
SQL, была я ожидал получить (желательно SQL) будет что-то вроде этого:
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(), если это возможно. Спасибо
Этот SQL кажется неполным/некорректным в некотором роде - он имеет больше ')', чем '('. Однако подзапрос, который я вижу пропущенный псевдоним, начинается в строке 7 - 'FROM (SELECT foo.id AS foo_id, '- и заканчивается на строке 17 - единственный') '. – IMSoP
Если посмотреть на это, я думаю, что подзапрос был создан SQLAlchemy, потому что он интерпретировал ваш запрос как подразумеваемое перекрестное соединение между' foo' и 'foo_max_time_q' (' FROM foo, (...) как foo_max_time_q') *, а также * ваша явная спецификация соединения ('JOIN (...) AS foo_max_time_q ON foo_max_time_q.foo_id = foo.id'). – IMSoP
@IMSoP : Вот как это порождается. Вот и вся проблема – slashdottir