Flask模型按15分钟时间段分组求平均行程时长的实现方案
没问题,我来帮你搞定这个按15分钟时间段分组计算平均行程时长的需求~
方案一:直接在查询中计算时间段(无需修改模型)
如果你不想改动现有模型,可以直接在查询语句里用SQL函数计算小时和15分钟区间,这样不用额外添加字段就能得到想要的结果:
from sqlalchemy import func, extract # 执行分组查询 results = db.session.query( # 提取出发小时 extract('hour', Journey.departure_time).label('departure_hour'), # 将分钟按15分钟分段:0对应00-14,1对应15-29,以此类推 func.floor(extract('minute', Journey.departure_time) / 15).label('departure_quarter'), # 计算每组的平均行程时长 func.avg(Journey.travel_duration).label('avg_duration') ).group_by( extract('hour', Journey.departure_time), func.floor(extract('minute', Journey.departure_time) / 15) ).all()
这种方式的好处是快速实现,不需要修改现有模型结构,适合临时或一次性的查询需求。
方案二:给模型添加混合属性(支持实例访问+SQL查询)
如果你希望像使用普通字段一样调用departure_hour和departure_quarter,可以给Journey模型添加混合属性(hybrid property),这样既支持Python实例层面的访问,也能在SQL查询中正常使用:
from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy import func, extract class Journey(db.Model): id = db.Column(db.Integer, primary_key=True) origin_id = db.Column(db.Integer, db.ForeignKey('location.id'), nullable=False) destination_id = db.Column(db.Integer, db.ForeignKey('location.id'), nullable=False) departure_time = db.Column(db.DateTime, nullable=False) travel_duration = db.Column(db.Integer, nullable=False) origin = db.relationship("Location", foreign_keys=[origin_id]) destination = db.relationship("Location", foreign_keys=[destination_id]) @hybrid_property def departure_hour(self): # Python实例层面:直接取出发时间的小时数 return self.departure_time.hour @departure_hour.expression def departure_hour(cls): # SQL查询层面:用extract函数提取小时 return extract('hour', cls.departure_time) @hybrid_property def departure_quarter(self): # Python实例层面:分钟//15得到0-3的区间标识 return self.departure_time.minute // 15 @departure_quarter.expression def departure_quarter(cls): # SQL查询层面:用floor函数计算15分钟区间 return func.floor(extract('minute', cls.departure_time) / 15)
添加完混合属性后,你就可以完全按照自己最初的想法写查询了:
results = db.session.query( Journey.departure_hour, Journey.departure_quarter, func.avg(Journey.travel_duration).label('avg_duration') ).group_by(Journey.departure_hour, Journey.departure_quarter).all()
这种方式的优势是代码更整洁,属性可以复用在其他查询或业务逻辑中,同时兼顾了Python代码和SQL查询的一致性。
额外优化:生成直观的时间段标签
如果需要更易读的时间段描述(比如10:00-10:14),可以在查询中直接拼接字符串:
results = db.session.query( func.concat( extract('hour', Journey.departure_time), ':', func.lpad(func.floor(extract('minute', Journey.departure_time)/15)*15, 2, '0'), '-', extract('hour', Journey.departure_time), ':', func.lpad((func.floor(extract('minute', Journey.departure_time)/15)+1)*15 -1, 2, '0') ).label('time_slot'), func.avg(Journey.travel_duration).label('avg_duration') ).group_by('time_slot').all()
返回的结果会直接显示类似10:00-10:14的时间段,更便于理解。
内容的提问来源于stack exchange,提问作者BenScape
相关产品推荐
相关产品推荐

