如何在Flask SQLAlchemy中实现SELECT DISTINCT YEAR()查询
在Flask-SQLAlchemy中获取指定用户的Report记录唯一年份列表
先回顾下你的场景:你已经定义了这样的Report模型:
class Report(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False) date = db.Column(db.Date, nullable=False)
想要获取指定用户(比如user_id=1)所有Report记录里的唯一年份列表,期望得到[2017, 2018, 2019],对应的原生SQL是:
SELECT DISTINCT YEAR(date) AS year FROM report WHERE user_id = 1 ORDER BY year ASC
下面就用Flask-SQLAlchemy来实现这个需求,两种方式都能完美匹配你的需求:
方法1:基础查询+结果转换
首先要导入SQLAlchemy的func工具,它能帮我们调用SQL里的内置函数:
from sqlalchemy import func
然后编写查询语句,完全对应你原生SQL的逻辑:
target_user_id = 1 # 执行查询,获取去重后的年份结果 year_results = db.session.query(func.year(Report.date).label('year'))\ .filter(Report.user_id == target_user_id)\ .distinct()\ .order_by('year')\ .all()
这时候year_results是一个包含元组的列表,比如[(2017,), (2018,), (2019,)],用列表推导式转成纯整数列表就可以了:
year_list = [year_tuple[0] for year_tuple in year_results] # 最终得到 [2017, 2018, 2019]
方法2:一步到位的简化写法
如果不想额外处理结果,可以用values_list直接提取扁平化的结果:
from sqlalchemy import func target_user_id = 1 year_list = list(db.session.query(func.year(Report.date))\ .filter(Report.user_id == target_user_id)\ .distinct()\ .order_by(func.year(Report.date))\ .values_list(func.year(Report.date), flat=True))
这里的values_list(..., flat=True)会直接返回可迭代的单一值序列,转成列表后就是你想要的结果。
简单说下逻辑:func.year(Report.date)对应SQL里的YEAR(date),distinct()实现去重,order_by()保证年份按升序排列,和你写的原生SQL逻辑完全一致。
内容的提问来源于stack exchange,提问作者Phil Gyford
相关产品推荐
相关产品推荐

