【问题标题】:SQLAlchemy place subqueries side by side instead of nestingSQLAlchemy 并排放置子查询而不是嵌套
【发布时间】:2020-03-16 15:35:18
【问题描述】:

我有一个包含两个子查询的查询。在 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 相同的 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';

这不会产生相同的结果,原因可能过于复杂,无法根据这个简化的示例进行解释。但是,如果我将最终查询更改为包含 sq1 中我并不真正需要的内容,SQLAlchemy 确实会做正确的事情,如下所示:

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

现在它返回具有正确结构的查询。有没有办法在不包含无价值数据的情况下强制并排子查询?

【问题讨论】:

    标签: python postgresql flask sqlalchemy


    【解决方案1】:

    你需要使用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
    

    【讨论】:

    • 这更接近正确的查询,但是这对子查询进行了错误的排序,因此在 SQL 中横向 sq2 位于 sq1 之前,然后您会得到 missing FROM-clause entry for table "anon_2" 的东西。更改select_from 中子查询的顺序不会改变任何内容。如果我从 Alchemy 获取生成的 SQL 并手动更改子查询的顺序,那么它可以工作。有什么办法对抗这个?或者这是炼金术中的一个错误?
    • 使用session.query(sq1.c.foo, sq2.c.foo, sq2.c.bar),它会以正确的顺序生成 from 子句。我不知道如何明确设置此顺序。
    • 是的,这也是我遇到的。不过感谢您的努力!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-19
    • 2017-08-03
    • 2019-08-16
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 2013-07-05
    相关资源
    最近更新 更多