I am struggling to understand the proper syntax for executing a subquery in SQLAlchemy when the value needs to be returned (i.e. not used in the WHERE).
I am using the declarative approach.
There are two models being used:
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)
The point of the query is to determine the current amount invoiced for each project by using a subquery to sum the related invoices. There are other reasons this is being done in a subquery rather than just a join so I really need to figure out the subquery issue.
This is an example of my current SA query:
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()
I have a feeling this is going to be embarrassing simple but I can't seem to crack the code on getting this to work.
I have tried just about every sample I can find with mixed results. If I leave out the .correlate() argument I receive the following error:
'Alias' object has no attribute 'MasterProjectID'
I have also tried adding the following statement to the end of the subquery() without any luck:
.correlate(ProjectMasters.MasterProjectID, ProjectInvoices.MasterProjectID)
If I do include the correlate argument then I receive the following error:
TypeError: Boolean value of this clause is not defined
Thanks for the help in advance...
Usually I would use a column_property
to handle such requirement, e.g.
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,
)
After that, you can use it like an ordinary attribute, e.g.
result = session.query(
ProjectMasters.MasterProjectID,
ProjectMasters.MasterProjectName,
ProjectMasters.billed_total.label('invoice_total'),
).filter(ProjectMasters.IsActive == 1).all()