This is the query I'm trying to produce through sqlalchemy
SELECT "order".id AS "id",
"order".created_at AS "created_at",
"order".updated_at AS "updated_at",
CASE
WHEN box.order_id IS NULL THEN "special"
ELSE "regular" AS "type"
FROM "order" LEFT OUTER JOIN box ON "order".id = box.order_id
Following sqlalchemy's documentation, I tried to achieve this using hybrid_property. This is what I have so far, and I'm not getting the right statement. It is not generating the case statement properly.
from sqlalchemy import (Integer, String, DateTime, ForeignKey, select, Column, create_engine)
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
Base = declarative_base()
class Order(Base):
__tablename__ = 'order'
id = Column(Integer, primary_key=True)
created_at = Column(DateTime)
updated_at = Column(DateTime)
order_type = relationship("Box", backref='order')
@hybrid_property
def type(self):
if not self.order_type:
return 'regular'
else:
return 'special'
class Box(Base):
__tablename__ = 'box'
id = Column(Integer, primary_key=True)
monthly_id = Column(Integer)
order_id = Column(Integer, ForeignKey('order.id'))
stmt = select([Order.id, Order.created_at, Order.updated_at, Order.type]).\
select_from(Order.__table__.outerjoin(Box.__table__))
print(str(stmt))
“hybrid” means the attribute has distinct behaviors defined at the class level and at the instance level. The hybrid extension provides a special form of method decorator, is around 50 lines of code and has almost no dependencies on the rest of SQLAlchemy.
InstrumentedAttribute is used to define a relationship to another table, for example. Query the database for results, and the resulting objects will have the reference filled in for you: for res in session.query(ResultLine). filter(somefilter): print res.item_reference_1.
The grouping is done with the group_by() query method, which takes the column to use for the grouping as an argument, same as the GROUP BY counterpart in SQL. The statement ends by calling subquery() , which tells SQLAlchemy that our intention for this query is to use it inside a bigger query instead of on its own.
The hybrid property must contain two parts for non-trivial expressions: a Python getter and a SQL expression. In this case, the Python side will be an if statement and the SQL side will be a case expression.
from sqlalchemy import case
from sqlalchemy.ext.hybrid import hybrid_property
@hybrid_property
def type(self):
return 'special' if self.order_type else 'regular'
@type.expression
def type(cls):
return case({True: 'special', False: 'regular'}, cls.order_type)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With