Python+MySQL实现新增产量数据模糊分类自动入库方法
需求背景
现有基于Python+MySQL开发的产量模糊分类项目,需新增数据录入能力:用户输入年份year与产量production_quantity后,程序自动匹配对应interval_id与fuzzy_id,写入productions表。
现有基础信息
涉及数据表结构
- productions(产量主表)
| id | year | production_quantity | interval_id | fuzzy_id |
|---|---|---|---|---|
| 1 | 2016 | 274317 | 11 | 6 |
| 2 | 2017 | 200916 | 7 | 3 |
| 3 | 2018 | 217246 | 8 | 4 |
| 4 | 2019 | 119830 | 3 | 2 |
| 5 | 2020 | 66640 | 1 | 1 |
- interval_fuzzy(区间规则表)
| id | interval_class | left_interval | right_nterval |
|---|---|---|---|
| 1 | A1 | 65000 | 85000 |
| 2 | A2 | 85000 | 105000 |
| 3 | A3 | 105000 | 125000 |
| 4 | A4 | 125000 | 145000 |
| 5 | A5 | 145000 | 165000 |
| 6 | A6 | 165000 | 185000 |
| 7 | A7 | 185000 | 205000 |
| 8 | A8 | 205000 | 225000 |
| 9 | A9 | 225000 | 245000 |
| 10 | A10 | 245000 | 265000 |
| 11 | A11 | 265000 | 285000 |
- fuzzy_value(模糊值映射表)
| id | interval_id | forecast_value |
|---|---|---|
| 1 | 1 | 75000 |
| 2 | 3 | 75000 |
| 3 | 7 | 215000 |
| 4 | 8 | 115000 |
| 5 | 11 | 275000 |
已实现功能
现有数据展示函数show_data()代码如下:
def show_data(): mycursor.execute("SELECT productions.year, productions.production_quantity, interval_fuzzy.interval_class, fuzzy_value.forecast_value FROM productions INNER JOIN interval_fuzzy ON productions.interval_id = interval_fuzzy.id INNER JOIN fuzzy_value ON productions.fuzzy_id = fuzzy_value.id") myresult = mycursor.fetchall() myresult.sort(key=lambda x: x[0]) df = pd.DataFrame(myresult, columns=['Year', 'Production', 'Interval Class', 'Forecast Value']) df['Forecast Value'] = df['Forecast Value'].shift(1) print(df)
函数运行输出:
Year Production Interval Class Forecast Value 1 2016 274317 A11 2 2017 200916 A7 275000 3 2018 217246 A8 215000 4 2019 119830 A3 115000 5 2020 66640 A1 75000
区间判定规则:根据输入的production_quantity数值,匹配interval_fuzzy表中满足区间范围的记录,对应得到区间类别与ID。
实现方案
需要编写的函数类型
共需实现4类逻辑:
- 输入校验函数:校验用户输入的年份、产量格式是否合法,拦截超出区间范围、格式错误的输入
- 区间匹配函数:根据输入的产量值,查询
interval_fuzzy表匹配对应interval_id - 模糊ID匹配函数:根据匹配到的
interval_id,查询fuzzy_value表得到对应fuzzy_id - 数据写入函数:将年份、产量、匹配到的两个ID组装后插入
productions表,带事务回滚机制避免脏数据
现有代码需要补充的内容
- 补全数据库异常处理逻辑:现有
show_data()没有做查询失败、连接断开的容错,新增写入逻辑必须加try...except捕获,写入失败时执行事务回滚。 - 修正字段名笔误:
interval_fuzzy表的右区间字段当前命名为right_nterval(拼写多了一个n),写查询语句时要和实际表字段保持一致,建议直接修改表字段名为right_interval减少后续出错概率。 - 统一区间边界规则:相邻区间的端点值(如85000、105000)统一归到右侧区间,采用左闭右开的判定逻辑(
left_interval ≤ 产量 < right_interval),避免端点值匹配不到区间。 - 补充交互入口:增加操作菜单,支持用户选择查看数据、录入数据、退出程序的操作。
- 补全模糊值映射:当前
fuzzy_value表仅存5条记录,仅覆盖interval_id为1、3、7、8、11的区间,其余区间需要先补充映射记录,否则录入对应区间的产量时会匹配不到fuzzy_id。
参考实现代码
def input_validate(year_input, prod_input): """输入格式与范围校验""" try: year = int(year_input) prod = int(prod_input) if 65000 <= prod <= 285000 and 2000 <= year <= 2100: return year, prod print("输入值超出合法范围,请重新输入") return None except ValueError: print("请输入合法的数字格式") return None def get_interval_id(prod_quantity): """根据产量匹配区间ID""" # 若已修正表字段名,将right_nterval改为right_interval sql = "SELECT id FROM interval_fuzzy WHERE left_interval <= %s AND right_nterval > %s" mycursor.execute(sql, (prod_quantity, prod_quantity)) res = mycursor.fetchone() return res[0] if res else None def get_fuzzy_id(interval_id): """根据区间ID匹配模糊值ID""" sql = "SELECT id FROM fuzzy_value WHERE interval_id = %s" mycursor.execute(sql, (interval_id,)) res = mycursor.fetchone() return res[0] if res else None def insert_production(year, prod_qty, interval_id, fuzzy_id): """写入产量主表""" sql = "INSERT INTO productions(year, production_quantity, interval_id, fuzzy_id) VALUES (%s, %s, %s, %s)" try: mycursor.execute(sql, (year, prod_qty, interval_id, fuzzy_id)) mydb.commit() print("数据录入成功") except Exception as e: mydb.rollback() print(f"写入失败:{str(e)}") # 程序交互入口 if __name__ == "__main__": while True: print("\n1. 查看数据 2. 录入新数据 3. 退出") choice = input("请输入操作选项:") if choice == "1": show_data() elif choice == "2": year_in = input("请输入年份:") prod_in = input("请输入产量:") valid_res = input_validate(year_in, prod_in) if not valid_res: continue year, prod = valid_res iid = get_interval_id(prod) if not iid: print("未匹配到对应产量区间") continue fid = get_fuzzy_id(iid) if not fid: print("当前区间未配置对应模糊值,请先补充fuzzy_value表记录") continue insert_production(year, prod, iid, fid) elif choice == "3": mycursor.close() mydb.close() break
内容的提问来源于stack exchange,提问作者twyla
相关产品推荐
相关产品推荐

