gpt4 book ai didi

python - SQLAlchemy:查找数组列之间的差异

转载 作者:行者123 更新时间:2023-11-29 14:37:23 24 4
gpt4 key购买 nike

我有一个名为 UnitOfWork 的表,它有 3 列 cases_identifiedcases_completedcases_double_check,所有这些是整数的 Postgresql 数组。

是否可以编写一个查询(或混合属性)来查找已识别但不在已完成或双重检查列中的案例?

这是我想出来的,但是 SQL 表达式不起作用:

@hybrid_property
def todo(self):
return [x for x in self.cases_identified
if x not in self.cases_completed and
x not in self.cases_double_check]

@todo.expression
def todo(cls):
return [x for x in cls.cases_identified
if x not in cls.cases_completed and
x not in cls.cases_double_check]

我在测试查询中得到的错误是:

test = Session.query(UnitOfWork.todo).first()
NotImplementedError: Operator 'contains' is not supported on this expression

最佳答案

对于这个答案,我假设 cls.cases_identifiedcls.cases_completedcls.cases_double_check 属于 postgresql .ARRAY(Integer) 在 Python 端输入。

您的 @todo.expression 应该只返回:一个 SQL 表达式。目前它正在尝试返回一个 python 列表。自 postgresql.ARRAY 以来引发异常不支持 in 运算符,尽管它有一个方法 contains ,它映射到 Postgresql 中的 @> 运算符并测试“元素是否是参数数组表达式元素的超集”。另一方面,这不是您想要的。你很幸运,你在那里有 if x not in ...,很简单

[x for x in cls.cases_identified]

似乎导致无限循环而不是异常。

获取 Postgresql 中数组之间的差异已涵盖 here广泛,但这里是你如何使用 SQLAlchemy 应用它,首先使用 an array constructor :

from sqlalchemy import func

...

class UnitOfWork(...):

@todo.expression
def todo(cls):
# Force correlation of `cls` from outer FROM objects. Use
# the `select()` shorthand method of `FunctionElement`.
identified = func.unnest(cls.cases_identified).select().correlate(cls)
completed = func.unnest(cls.cases_completed).select().correlate(cls)
double_check = func.unnest(cls.cases_double_check).select().correlate(cls)
# Create the subquery statement
stmt = identified.except_(completed.union(double_check))
# Uses the `func` generic for ARRAY constructor from
# subquery syntax. The subquery statement has to be
# converted to a "scalar subquery" in the eyes of SQLA
# (really just a subquery returning 1 col) in order
# to remove it from the FROM clause hierarchy.
return func.array(stmt.as_scalar())

这有一个不提供任何 FROM 对象的缺点(因为它与封闭查询中的所有内容相关联),因此您必须像这样发出原始查询:

test = Session.query(UnitOfWork.todo).select_from(UnitOfWork).first()

您还可以使用 Postgresql intarray module为无空整数数组提供特殊函数和运算符:

class UnitOfWork(...):

@todo.expression
def todo(cls):
return (cls.cases_identified - cls.cases_completed -
cls.cases_double_check)

请注意,您必须先在 Postgresql 中安装扩展:

CREATE EXTENSION intarray;

关于python - SQLAlchemy:查找数组列之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42269201/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com