簡體   English   中英

sqlalchemy 全外連接

[英]sqlalchemy FULL OUTER JOIN

如何在 orm 級別的 sqlalchemy 中實現 FULL OUTER JOIN。

這是我的代碼:

q1 = (db.session.query(
        tb1.user_id.label('u_id'),
        func.count(tb1.id).label('tb1_c')
    )
    .group_by(tb1.user_id)
)
q2 = (db.session.query(
        tb2.user_id.label('u_id'),
        func.count(tb2.id).label('tb2_c')
    )
    .group_by(tb2.user_id)
)

以上兩個查詢,我想對它們應用 FULL OUTER JOIN。

從 1.1. sqlalchemy 現在完全支持 FULL OUTER JOINS。 請參閱此處: https : //docs.sqlalchemy.org/en/13/orm/query.html#sqlalchemy.orm.query.Query.join.params.full

因此,對於您的代碼,您需要執行以下操作:

q1 = (db.session.query(
        tb1.user_id.label('u_id'),
        func.count(tb1.id).label('tb1_c')
    )
    .group_by(tb1.user_id)
).cte('q1')

q2 = (db.session.query(
        tb2.user_id.label('u_id'),
        func.count(tb2.id).label('tb2_c')
    )
    .group_by(tb2.user_id)
).cte('q2')

result = db.session.query(
    func.coalesce(q1.u_id, q2.u_id).label('u_id'),
    q1.tb1_c,
    q2.tb2_c
).join(
    q2,
    q1.u_id == q2.u_id,
    full=True
)

請注意,與任何 FULL OUTER JOIN 一樣, tb1_ctb2_c可能為空,因此您可能希望對它們應用合並。

首先, sqlalchemy不支持開箱即用的FULL JOIN ,這是有充分理由的。 因此,提出的任何解決方案都將由兩部分組成:

  1. 缺少功能的解決方法
  2. 為該變通方法構建查詢的sqlalchemy語法

現在,出於避免FULL JOIN的原因,請閱讀一些舊博客Better Alternatives to a FULL OUTER JOIN 從這個博客中,我將了解如何通過向缺失的列添加0值並在UNION ALL上聚合 ( SUM ) 來避免FULL JOIN SA 代碼可能如下所示:

q1 = (session.query(
        tb1.user_id.label('u_id'),
        func.count(tb1.id).label('tb1_c'),
        literal(0).label('tb2_c'), # @NOTE: added 0
      ).group_by(tb1.user_id))
q2 = (session.query(
        tb2.user_id.label('u_id'),
        literal(0).label('tb1_c'), # @NOTE: added 0
        func.count(tb2.id).label('tb2_c')
      ).group_by(tb2.user_id))

qt = union_all(q1, q2).alias("united")
qr = select([qt.c.u_id, func.sum(qt.c.tb1_c), func.sum(qt.c.tb2_c)]).group_by(qt.c.u_id)

完成上面的查詢后,我實際上可能會考慮其他選項:

  • 只需分別執行這兩個查詢並聚合 Python 本身中已有的結果(對於不是那么大的結果集)
  • 鑒於它看起來像某種報告功能而不是業務模型工作流,​​創建一個SQL查詢並直接通過engine執行它。 (只有當它確實表現更好時)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM