SQLAlchemy размещает подзапросы рядом, а не во вложении - PullRequest
1 голос
/ 16 марта 2020

У меня есть запрос, который включает в себя два подзапроса. В SQL это выглядит примерно так:

SELECT sq2.foo,
       sq2.bar
FROM (
      SELECT foo FROM bar WHERE foo = '123'
) AS sq1,
LATERAL (
      SELECT foo, bar FROM bar WHERE s1.foo = 'zomething'
) AS sq2
WHERE sq2.foo = 'something';

Это то, что мне нужно от SQLAlchemy. Когда я перевожу его на алхимию, я получаю примерно следующее:

sq1 = session.query(Bar.foo).filter(Bar.foo == '123').subquery()
sq2 = session.query(Bar.foo).filter(sq1.foo == 'zomething').subquery().lateral()
session.query(sq2.foo, sq2.bar).filter(sq.foo = 'something').all()

Однако, это не означает то же самое, что и верхний SQL, а скорее вкладывает такие запросы:

SELECT sq2.foo,
       sq2.bar
FROM LATERAL (
    SELECT foo, bar FROM (
        SELECT foo FROM bar WHERE foo = '123'
    ) AS sq1,
    bar
    WHERE sq1.foo = 'zomething'
) AS sq2
WHERE sq2.foo = 'something';

Это не дает тот же результат по причинам, которые, вероятно, слишком сложны для объяснения на основе этого упрощенного примера. SQLAlchemy, однако, делает правильные вещи, если я изменяю окончательный запрос, чтобы включить что-то из sq1, которое мне действительно не нужно, например так:

session.query(sq2.foo, sq2.bar, sq1.foo).filter(sq.foo = 'something').all()

Теперь он возвращает запрос с правильной структурой , Есть ли способ принудительно создавать подзапросы без добавления бесполезных данных?

1 Ответ

1 голос
/ 16 марта 2020

Вам нужно использовать select_from

sq1 = session.query(Bar.foo).filter(Bar.foo == '123').subquery().alias('sq1')
sq2 = session.query(Bar.foo, Bar.bar).filter(sq1.c.foo == 'zomething').subquery().lateral('sq2')
q = session.query(sq2.c.foo, sq2.c.bar).select_from(sq1, sq2).filter(sq2.c.foo == 'something')

# >> print(q)
# SELECT sq2.foo AS sq2_foo, sq2.bar AS sq2_bar 
# FROM LATERAL (SELECT bar.foo AS foo, bar.bar AS bar 
# FROM bar 
# WHERE sq1.foo = %(foo_1)s) AS sq2, (SELECT bar.foo AS foo 
# FROM bar 
# WHERE bar.foo = %(foo_2)s) AS sq1
# WHERE sq2.foo = %(foo_3)s
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...