3

当需要返回值时(即未在 WHERE 中使用),我正在努力理解在 SQLAlchemy 中执行子查询的正确语法。

我正在使用声明性方法。

有两种模型被使用:

class ProjectInvoices(Base):
    InvoiceID = Column(Integer(unsigned=True), default=0, primary_key=True, autoincrement=True)
    MasterProjectID = Column(Integer(unsigned=True), index=True, nullable=False)
    ExpenseAmount = Column(Numeric(10, 2), default=0)
    HoursAmount = Column(Numeric(10, 2), default=0)
    IsVoid = Column(Boolean, default=0, index=True)
    IsSubmit = Column(Boolean, default=0, index=True)

class ProjectMasters(Base):
    MasterProjectID = Column(Integer(unsigned=True), default=0, primary_key=True, autoincrement=True)
    MasterProjectName = Column(Unicode(255))
    MasterProjectMemo = Column(UnicodeText)
    IsActive = Column(Boolean, default=0, index=True)

查询的重点是通过使用子查询汇总相关发票来确定每个项目的当前发票金额。还有其他原因,这是在子查询中完成的,而不仅仅是一个连接,所以我真的需要弄清楚子查询问题。

这是我当前 SA 查询的示例:

sqry = session.query(
  func.sum(
    func.ifnull(ProjectInvoices.ExpenseAmount, 0) 
    + func.ifnull(ProjectInvoices.HoursAmount, 0))).label('billed_total')
).filter(and_(ProjectInvoices.IsVoid == 0, ProjectInvoices.IsSubmit == 1)
).subquery()

result = session.query(
  ProjectMasters.MasterProjectID, 
  ProjectMasters.MasterProjectName, 
  sqry.columns.billed_total.label('invoice_total')
).filter(ProjectMasters.IsActive == 1).all()

我有一种感觉,这将是令人尴尬的简单,但我似乎无法破解让它工作的代码。

我已经尝试了几乎所有我能找到的样本,结果好坏参半。如果我省略 .correlate() 参数,我会收到以下错误:

'Alias' object has no attribute 'MasterProjectID'

我还尝试将以下语句添加到 subquery() 的末尾,但没有任何运气:

.correlate(ProjectMasters.MasterProjectID, ProjectInvoices.MasterProjectID)

如果我确实包含了相关参数,那么我会收到以下错误:

TypeError: Boolean value of this clause is not defined

我在这里先向您的帮助表示感谢...

4

1 回答 1

6

通常我会使用 acolumn_property来处理这样的要求,例如

class ProjectMasters(Base):
    ...

    billed_total = column_property(
        select(
            [func.sum(
                func.coalesce(ProjectInvoices.ExpenseAmount, 0)
                + func.coalesce(ProjectInvoices.HoursAmount, 0)
            )],
            and_(
                MasterProjectID == ProjectInvoices.MasterProjectID,
                ProjectInvoices.IsVoid == False,
                ProjectInvoices.IsSubmit == True,
            ),
        ).label('billed_total'),
        deferred=True,
    )

之后,您可以像使用普通属性一样使用它,例如

result = session.query(
    ProjectMasters.MasterProjectID, 
    ProjectMasters.MasterProjectName, 
    ProjectMasters.billed_total.label('invoice_total'),
).filter(ProjectMasters.IsActive == 1).all()
于 2011-10-17T03:03:28.140 回答