我几乎想出了如何将此查询翻译成SQLAlchemy
:
select u.* from (select
unit_id,
activity,
max(occurred_at) maxOA
from Activity
group by unit_id) a1
inner join Activity a2 on
a2.unit_id = a1.unit_id and a2.occurred_at = a1.maxOA
inner join Unit u on
u.id = a2.unit_id where a2.activity = 'activateReq';
我的表看起来像这样(gDB是保存我的SQLAlchemy数据库连接的全局变量):
class Unit(gDB.Model):
__tablename__ = 'Unit'
id = gDB.Column('id', gDB.Integer(), primary_key=True)
owner_id = gDB.Column('owner_id', gDB.ForeignKey('User.id'))
owner = gDB.relationship(User, primaryjoin=owner_id == User.id)
unitNumber = gDB.Column('unit_number', gDB.Integer())
street = gDB.Column('street', gDB.String(255))
city = gDB.Column('city', gDB.String(255))
state = gDB.Column('state', gDB.String(2))
zip = gDB.Column('zip', gDB.String(9))
serviceInstallDate = gDB.Column('service_install_date', gDB.DateTime())
activity = gDB.relationship('Activity', backref='unit_id', lazy='select', order_by="desc(Activity.occurredAt)")
def __repr__(self):
return '<Unit: {0} {1}>'.format(self.unitNumber, self.street)
class Activity(gDB.Model):
__tablename__ = 'Activity'
id = gDB.Column('id', gDB.Integer(), primary_key=True)
unitID = gDB.Column('unit_id', gDB.ForeignKey('Unit.id'))
unit = gDB.relationship(Unit, primaryjoin=unitID == Unit.id)
agentID = gDB.Column('agent_id', gDB.ForeignKey('User.id'))
agent = gDB.relationship(User, primaryjoin=agentID == User.id)
occurredAt = gDB.Column('occurred_at', gDB.DateTime())
activity = gDB.Column('activity', gDB.String(32))
notes = gDB.Column('notes', gDB.String())
def __repr__(self):
return '<Activity: {0} {1}>'.format(self.activity, self.occurredAt)
我已经走到这一步了:
db.session.query(Activity.unitID, Activity.activity, func.max(Activity.occurredAt).label("maxOA"))
.group_by(Activity.unitID)
.subquery()
a2 = expression.alias(Activity)
u = expression.alias(Unit)
q = db.session.query(a1)
.join(a2, and_(a2.c.unit_id == a1.c.unit_id, a2.c.occurred_at == a1.c.maxOA))
.join(u, u.c.id == a2.c.unit_id).filter(a2.c.activity == 'activateReq')
q.all()
q.all()
正在返回正确的行集,但我想要Unit
的列,而不是子查询a1
的列。
更新
我已经接近了:诀窍是query()
所需的列(在本例中为u
的所有列),然后select_from()
子查询a1
}:
q = db.session.query(u).select_from(a1).join(a2, and_(a2.c.unit_id == a1.c.unit_id, a2.c.occurred_at == a1.c.maxOA)).join(u, u.c.id == a2.c.unit_id).filter(a2.c.activity=='activateReq')
现在的问题是生成的Unit
个实例没有相关的User
(owner_id
/ owner
个)对象;我的Jinja模板尝试引用user.owner,我得到了
'sqlalchemy.util._collections.result object' has no attribute 'owner'
我也不知道这是否是最简洁或最有效的方式。
答案 0 :(得分:1)
啊!我想到了。我使用expression.alias()
代替orm.aliased()
。它应该是这样的:
a1 = gDB.session.query(Activity.unitID, Activity.activity, func.max(Activity.occurredAt).label("maxOA")) \
.group_by(Activity.unitID) \
.subquery()
a2 = aliased(Activity, name="a2")
u = aliased(Unit, name="u")
q = gDB.session.query(u).select_from(a1) \
.join(a2, and_(a2.unitID == a1.c.unit_id, a2.occurredAt == a1.c.maxOA)) \
.join(u, u.id == a2.unitID).filter(a2.activity == 'activateReq')