SQLAlchemy中的右外部连接

2024-05-13 05:52:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我在下面定义了两个表beardmoustache

+--------+---------+------------+-------------+
| person | beardID | beardStyle | beardLength |
+--------+---------+------------+-------------+

+--------+-------------+----------------+
| person | moustacheID | moustacheStyle |
+--------+-------------+----------------+

我在PostgreSQL中创建了一个SQL查询,它将这两个表组合起来,并生成以下结果:

+--------+---------+------------+-------------+-------------+----------------+
| person | beardID | beardStyle | beardLength | moustacheID | moustacheStyle |
+--------+---------+------------+-------------+-------------+----------------+
| bob    | 1       | rasputin   | 1           |             |                |
+--------+---------+------------+-------------+-------------+----------------+
| bob    | 2       | samson     | 12          |             |                |
+--------+---------+------------+-------------+-------------+----------------+
| bob    |         |            |             | 1           | fu manchu      |
+--------+---------+------------+-------------+-------------+----------------+

查询:

SELECT * FROM beards LEFT OUTER JOIN mustaches ON (false) WHERE  person = "bob"
UNION ALL
SELECT * FROM beards b RIGHT OUTER JOIN mustaches ON (false) WHERE  person = "bob"

但是我不能创建它的SQLAlchemy表示。我尝试了从实现from_statementouterjoin的几种方法,但没有一种真正起作用。有人能帮我吗?


Tags: fromfalseonselectpersonbobouterjoin
3条回答

@Francis Psuggestion中,我想到了这个片段:

q1 = session.\
     query(beard.person.label('person'),
           beard.beardID.label('beardID'),
           beard.beardStyle.label('beardStyle'),
           sqlalchemy.sql.null().label('moustachID'),
           sqlalchemy.sql.null().label('moustachStyle'),
     ).\
     filter(beard.person == 'bob')

q2 = session.\
     query(moustache.person.label('person'),
           sqlalchemy.sql.null().label('beardID'), 
           sqlalchemy.sql.null().label('beardStyle'),
           moustache.moustachID,
           moustache.moustachStyle,
     ).\
     filter(moustache.person == 'bob')

result = q1.union(q2).all()

不过,这是可行的,但你不能称之为一个答案,因为它似乎是一个黑客。这是sqlalchemy中应该有RIGHT OUTER JOIN的另一个原因。

以下是我的作品,ORM风格:

from sqlalchemy.sql import select, false

stmt = (
    select([Beard, Moustache])
    .select_from(
        outerjoin(Beard, Moustache, false())
    ).apply_labels()
).union_all(
    select([Beard, Moustache])
    .select_from(
        outerjoin(Moustache, Beard, false())
    ).apply_labels()
)

session.query(Beard, Moustache).select_entity_from(stmt)

它似乎是独立工作的,但似乎不可能与另一个选定的表达式结合起来

在SQL中,A RIGHT OUTER JOIN B等同于B LEFT OUTER JOIN A。因此,从技术上讲,不需要在RIGHT OUTER JOINAPI中——通过切换目标的位置“selectable”和连接的位置“selectable”,也可以做到这一点。SQL炼金术为此提供了一个API:

# this **fictional** API:
query(A).join(B, right_outer_join=True)  # right_outer_join doesn't exist in SQLA!

# can be implemented in SQLA like this:
query(A).select_entity_from(B).join(A, isouter=True)

请参阅SQLAQuery.join() doc,控制从“加入什么”部分。

相关问题 更多 >