如何在SQLAlchemy中编写嵌套的联结(OR和AND子句)?

9

有人知道如何在SQLAlchemy中生成嵌套的联结吗?

我有一些类似于下面的Python代码:

import sqlalchemy as sa

a = sa.and_(mytable.col1 > 1, mytable.col2 < 3)
b = sa.and_(mytable.col1 < 1, mytable.col4 == None)
clause_args = [a, b] 
or_clauses = sa.or_(*clause_args)
session.query(mytable).filter(mytable.status.in_([1,2,3,4])).filter(or_clauses)

注意,以下只是一些伪代码,用于演示我遇到的语法问题。 不要太多分析查询逻辑。 我只想找到一种在AND和OR块周围添加括号的方法。 SQLAlchemy生成类似于此的SQL:

SELECT
     id, status, name, col1, col2, col3, col4
FROM mytable
WHERE
    status in (1,2,3,4)
AND (col1 > 1 
     AND col2 < 3
     OR col1 < 1
     AND col4 is NULL);

请注意,AND条件在OR之间的逻辑AND块周围没有括号:
AND (col1 > 1 
     AND col2 < 3
     OR col1 < 1
     AND col4 is NULL);

我希望在使用or_和and_连接符时强制使用括号过滤条件。

我希望将条件用括号括起来,以便SQL输出如下:

SELECT
     id, status, name, col1, col2, col3, col4
FROM mytable
WHERE
    status in (1,2,3,4)
AND ((col1 > 1 
     AND col2 < 3)
     OR (col1 < 1
     AND col4 is NULL));

有没有人能够建议如何实现这一点?

谢谢!


看这里:http://stackoverflow.com/questions/26154009/how-to-nest-conjunctions-or-and-and-in-sqlalchamey - user3745855
OP,你最终找到解决方案了吗? - Curtwagner1984
2个回答

19

使用self_group()。 文档链接:self_group

示例的解决方案如下:

import sqlalchemy as sa

a = sa.and_(mytable.col1 > 1, mytable.col2 < 3).self_group()
b = sa.and_(mytable.col1 < 1, mytable.col4 == None).self_group()
clause_args = [a, b] 
or_clauses = sa.or_(*clause_args)
session.query(mytable).filter(mytable.status.in_([1,2,3,4])).filter(or_clauses)

3
您提供的同一份文档明确说明:“self_group()方法的应用是自动的 - 最终用户代码不应直接使用此方法”。链接在这里:https://docs.sqlalchemy.org/en/13/core/sqlelement.html#sqlalchemy.sql.expression.ClauseElement.self_group - tombishop83
1
从我的经验来看,自组行为的应用是不一致的 - 例如,在SQLAlchemy 1.3.16上,我可以通过在“or_”块中包装一系列“and_”块来触发该行为。通过self_group()强制执行行为可以很好地断言条件语句,无论解析器将来如何调整其自身行为。虽然这只是个人经历,但这种“自动”应用在停止自动应用时会导致许多非常微妙的查询错误。 - bsplosion
@tombishop83 有更好的解决方案吗? - Curtwagner1984

1

如果我理解正确,你所寻找的括号并不需要,因为AND的优先级高于OR。


Yap -> https://www.alphacodingskills.com/postgresql/notes/postgresql-operators-precedence.php - Rui Martins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接