[英]sqlalchemy FULL OUTER JOIN
How to implement FULL OUTER JOIN in sqlalchemy on orm level.如何在 orm 级别的 sqlalchemy 中实现 FULL OUTER JOIN。
Here my code:这是我的代码:
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)
)
above two queries and I want to apply FULL OUTER JOIN on them.以上两个查询,我想对它们应用 FULL OUTER JOIN。
Since 1.1.从 1.1. sqlalchemy now fully supports FULL OUTER JOINS.
sqlalchemy 现在完全支持 FULL OUTER JOINS。 See here: https://docs.sqlalchemy.org/en/13/orm/query.html#sqlalchemy.orm.query.Query.join.params.full
请参阅此处: https : //docs.sqlalchemy.org/en/13/orm/query.html#sqlalchemy.orm.query.Query.join.params.full
So for your code you would want to do:因此,对于您的代码,您需要执行以下操作:
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
)
Note that as with any FULL OUTER JOIN, tb1_c
and tb2_c
may be null so you might want to apply a coalesce on them.请注意,与任何 FULL OUTER JOIN 一样,
tb1_c
和tb2_c
可能为空,因此您可能希望对它们应用合并。
First of all, sqlalchemy
does not support FULL JOIN
out of the box, and for some good reasons.首先,
sqlalchemy
不支持开箱即用的FULL JOIN
,这是有充分理由的。 So any solution proposed will consist of two parts:因此,提出的任何解决方案都将由两部分组成:
sqlalchemy
syntax to build a query for that work-aroundsqlalchemy
语法Now, for the reasons to avoid the FULL JOIN
, please read some old blog Better Alternatives to a FULL OUTER JOIN .现在,出于避免
FULL JOIN
的原因,请阅读一些旧博客Better Alternatives to a FULL OUTER JOIN 。 From this very blog I will take the idea of how to avoid FULL JOIN
by adding 0
values to the missing columns and aggregating ( SUM
) on UNION ALL
intead.从这个博客中,我将了解如何通过向缺失的列添加
0
值并在UNION ALL
上聚合 ( SUM
) 来避免FULL JOIN
。 SA code might look something like below: 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)
Having composed the query above, I actually might consider other options:完成上面的查询后,我实际上可能会考虑其他选项:
SQL
query and execute it directly via engine
.SQL
查询并直接通过engine
执行它。 (only if it really is much better performing though)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.