如何使用sqlite3模块计算SQLite中最近N条记录的平均值?
问题
我正在使用Python 3.11,结合tkinter和sqlite3包开发体重追踪程序。已创建包含四列的数据库表weights,其中一列名为weight,数据类型为real(小数/浮点数)。我希望编写一个使用cursor.execute的函数,选取weight列最近7条记录,计算并返回其平均值。
我知道SQLite3内置AVG()函数,但它默认计算全列平均值,不知道如何只计算最近N条;也试过cursor.fetchmany(7)方法,但取出的数据是元组,手动计算平均值时遇到元组无法与数值直接交互的错误。
当前函数代码执行后得到的是全列平均值,而非最近7条的:
def average_query(): #Create a database or connect to one conn = sqlite3.connect('weight_tracker.db') #Create cursor c = conn.cursor() my_average = c.execute("SELECT round(avg(weight)) FROM weights ORDER BY oid DESC LIMIT 7") my_average = c.fetchall() my_average = my_average[0][0] #Create labels on screen average_label = Label(root,text=f"Your average 7-day rolling weight is {my_average} pounds.") average_label.grid(row=9, column=0, columnspan=2) #Commit changes conn.commit() #Close connection conn.close()
解决方案
核心问题是SQL语句的逻辑顺序错误:原语句先对全列计算AVG(weight),再对结果取前7条(但聚合函数返回的只有1条结果,所以LIMIT 7完全不起作用)。正确逻辑是先筛选出最近7条记录,再对这7条计算平均值。
方法1:修正SQL语句(推荐)
调整SQL结构,用子查询先获取最近7条的weight值,再对这些值计算平均值:
def average_query(): conn = sqlite3.connect('weight_tracker.db') c = conn.cursor() # 先取最近7条记录的weight,再计算平均值并四舍五入 c.execute("SELECT ROUND(AVG(weight)) FROM (SELECT weight FROM weights ORDER BY oid DESC LIMIT 7)") my_average = c.fetchone()[0] # fetchone比fetchall更高效,直接取唯一结果 average_label = Label(root, text=f"Your average 7-day rolling weight is {my_average} pounds.") average_label.grid(row=9, column=0, columnspan=2) conn.commit() conn.close()
- 子查询
(SELECT weight FROM weights ORDER BY oid DESC LIMIT 7)按oid倒序取出最近7条的weight值 - 外层查询对这7条数据计算平均值,再用
ROUND()处理小数位数 - 用
fetchone()替代fetchall(),直接获取聚合后的唯一结果,代码更简洁
方法2:手动计算平均值(适合需额外处理数据的场景)
如果需要先获取7条数据再手动计算,可通过遍历元组提取数值:
def average_query(): conn = sqlite3.connect('weight_tracker.db') c = conn.cursor() c.execute("SELECT weight FROM weights ORDER BY oid DESC LIMIT 7") recent_weights = c.fetchall() # 遍历元组提取数值,计算平均值,处理无数据的情况 total = sum(weight[0] for weight in recent_weights) my_average = round(total / len(recent_weights)) if recent_weights else 0 average_label = Label(root, text=f"Your average 7-day rolling weight is {my_average} pounds.") average_label.grid(row=9, column=0, columnspan=2) conn.commit() conn.close()
recent_weights是包含7个元组的列表(每个元组为(weight_value,)),通过weight[0]提取浮点数- 增加空数据判断,避免除以0的错误
内容的提问来源于stack exchange,提问作者Jay_SK
相关产品推荐
相关产品推荐

