我有一个sqlalchemy类,该类代表具有列FileID
和SettlementDate
的表。我想创建一个混合属性,以说明给定实例是否为其FileID
的最大值SettlementDate
,以及要在查询时使用的关联表达式。我已经成功地使该属性正常工作,但是在表达上却有些挣扎。这是现有的模型:
class Hdr(model.Base):
id = Column('ID', Integer, primary_key=True)
file_id = Column('FileID', BIGINT, ForeignKey('FileRegister.Files.ID'))
settlement_date = Column('SettlementDate', Date)
@hybrid_property
def is_latest(self):
subquery = (
object_session(self)
.query(func.max(Hdr.file_id).label('file_id'))
.group_by(Hdr.settlement_date)
.subquery()
)
return (
object_session(self)
.query(func.count(Hdr.file_id).cast(Boolean))
.filter(subquery.c.file_id==self.file_id)
.scalar()
)
我想我可以按照以下方式做点事情:
subquery = (
select((func.max(Hdr.file_id).label('file_id'), ))
.group_by(Hdr.settlement_date)
.alias('a')
)
s = select(
case(
whens=[
(Hdr.file_id.in_(subquery), 1)
],
else_=0
)
)
但这会引发错误Boolean value of this clause is not defined
。
任何帮助将不胜感激!
跟踪如下:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
c:\Users\\venvs\insight\lib\site-packages\sqlalchemy-1.3.0b3-py3.7-win-amd64.egg\sqlalchemy\sql\selectable.py in __init__(self, columns, whereclause, from_obj, distinct, having, correlate, prefixes, suffixes, **kwargs)
2889 try:
-> 2890 cols_present = bool(columns)
2891 except TypeError:
c:\Users\\venvs\insight\lib\site-packages\sqlalchemy-1.3.0b3-py3.7-win-amd64.egg\sqlalchemy\sql\elements.py in __bool__(self)
515 def __bool__(self):
--> 516 raise TypeError("Boolean value of this clause is not defined")
517
TypeError: Boolean value of this clause is not defined
During handling of the above exception, another exception occurred:
ArgumentError Traceback (most recent call last)
<ipython-input-20-4946a4bf7faa> in <module>
10 (Hdr.file_id.in_(subquery), 1)
11 ],
---> 12 else_=0
13 )
14 )
<string> in select(columns, whereclause, from_obj, distinct, having, correlate, prefixes, suffixes, **kwargs)
<string> in __init__(self, columns, whereclause, from_obj, distinct, having, correlate, prefixes, suffixes, **kwargs)
c:\Users\\venvs\insight\lib\site-packages\sqlalchemy-1.3.0b3-py3.7-win-amd64.egg\sqlalchemy\util\deprecations.py in warned(fn, *args, **kwargs)
128 )
129
--> 130 return fn(*args, **kwargs)
131
132 doc = fn.__doc__ is not None and fn.__doc__ or ""
c:\Users\\venvs\insight\lib\site-packages\sqlalchemy-1.3.0b3-py3.7-win-amd64.egg\sqlalchemy\sql\selectable.py in __init__(self, columns, whereclause, from_obj, distinct, having, correlate, prefixes, suffixes, **kwargs)
2891 except TypeError:
2892 raise exc.ArgumentError(
-> 2893 "columns argument to select() must "
2894 "be a Python list or other iterable"
2895 )
ArgumentError: columns argument to select() must be a Python list or other iterable
答案 0 :(得分:1)
问题是
s = select(case(...))
select()
的第一个参数应该是一系列列元素或from子句对象。似乎SQLAlchemy有时会通过执行bool(columns)
来检查所传递的序列是否为空。解决方案是像创建subquery
一样简单地按顺序包装它:
s = select([case(...)])
在混合属性的“ Python端”中,而不是计算任何file_id
中最大的settlement_date
是否恰好与实例匹配,您可以按实例的settlement_date
进行过滤并检查最大值:
class Hdr(model.Base):
@hybrid_property
def is_latest(self):
max_file_id = (
object_session(self)
.query(func.max(Hdr.file_id))
.filter(Hdr.settlement_date == self.settlement_date)
.scalar()
)
return max_file_id == self.file_id
在表达式中,您不需要将布尔表达式包装在标量子查询中,而是返回布尔表达式本身:
@is_latest.expression
def is_latest(cls):
hdr_alias = aliased(Hdr)
subquery = (
select([func.max(hdr_alias.file_id)])
.group_by(hdr_alias.settlement_date)
)
return cls.file_id.in_(subquery)