【问题标题】:SQLAlchemy - How to add dynamic left joins to a query?SQLAlchemy - 如何向查询添加动态左连接?
【发布时间】:2016-10-19 21:54:17
【问题描述】:

我有六个表,建模如下:

+--< B >--C
| 
A
|
+--< D >--E

我希望能够动态查询这些选项中的任何一个:

A
A, B, C
A, D, E
A, B, C, D E

例如,查询所有四个看起来像

q = session.query(A, B, C, D, E) \
    .outerjoin(B, A.id == B.a_id).outerjoin(C, C.id == B.c_id)
    .outerjoin(D, A.id == D.a_id).outerjoin(E, E.id == D.e_id)

我可以将模型附加到列表中并在select 子句中动态使用它们。但是,我无法弄清楚如何动态附加连接。这是我目前所拥有的:

from sqlalchemy import outerjoin

models = [A]
joins = []

if foo:
    models.append(B)
    models.append(C)
    joins.append(outerjoin(A, B, A.id == B.a_id))
    joins.append(outerjoin(B, C, C.id == B.c_id))

if bar:
    models.append(D)
    models.append(E)
    joins.append(outerjoin(A, D, A.id == D.d_id))
    joins.append(outerjoin(D, E, E.id == D.e_id))

q = session.query(*models)
# How do I attach my joins list to this query?

我尝试了以下方法,但没有成功,即使成功了,我也会假设foobar 都是False 的情况会留下一个空的FROM 子句。

q = q.select_from(*joins)

当然可以去掉joins列表,在执行q = session.query(*models)之后重复if条件,如下,但我宁愿执行一次条件逻辑。

if foo:
    q = q.outerjoin(B, A.id == B.a_id).outerjoin(C, C.id == B.c_id)

if bar:
    q = q.outerjoin(D, A.id == D.a_id).outerjoin(E, E.id == D.e_id)

【问题讨论】:

    标签: python python-2.7 sqlalchemy


    【解决方案1】:

    每个outerjoin(和其他 SLQALchemy 查询方法)都会修改一个 query 对象并返回一个新查询 - 您可以通过调用 outerjoin(或 filter 等)方法进一步修改它。 因此,只需使用 for 循环重复修改您的查询,并为您使用条件指定的每组外连接参数添加一个额外的 outerjoin。参数本身可以是你在前面加上* 的元组,就像你为模型做的那样

    models = [A]
    joins = []
    
    if foo:
        models.append(B)
        models.append(C)
        joins.append((A, B, A.id == B.a_id))
        joins.append((B, C, C.id == B.c_id))
    
    if bar:
        models.append(D)
        models.append(E)
        joins.append((A, D, A.id == D.d_id))
        joins.append((D, E, E.id == D.e_id))
    
    q = session.query(*models)
    for join_args in joins:
         q = q.outerjoin(*join_args)
    
    # q is now ready to go with all outerjoins specified.
    

    【讨论】:

    • 它不返回一个新的查询,它返回一个连接对象
    【解决方案2】:

    @jsbueno 的验证答案给了我解决问题的提示,但它并没有 100% 对我有用。可能是版本问题,因此提供了一个对我有用的几乎类似的解决方案。

    models = [A]
    joins = []
    
    if foo:
        joins.append((B, A.id == B.a_id))
        joins.append((C, C.id == B.c_id))
    
    if bar:
        joins.append((D, A.id == D.d_id))
        joins.append((E, E.id == D.e_id))
    
    q = session.query(*models)
    for join_args in joins:
         q = q.outerjoin(*join_args)
    
    q.all() #This shall give you the required output.
    

    【讨论】:

      猜你喜欢
      • 2016-05-08
      • 2016-04-17
      • 2017-05-26
      • 1970-01-01
      • 2016-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-15
      相关资源
      最近更新 更多