SQLAlchemy - 如何向查询添加动态左连接?

时间:2016-06-18 00:24:34

标签: python python-2.7 sqlalchemy

我有六张表,模仿如下:

+--< 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的情况会留空{{ 1}}子句。

FROM

当然,我可以在执行q = q.select_from(*joins) 之后删除joins列表并重复if条件,如下所示,但我宁愿执行一次条件逻辑。 / p>

q = session.query(*models)

2 个答案:

答案 0 :(得分:3)

每个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.

答案 1 :(得分:0)

@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.