直接连MySQL取数绘图可行,但需分离数据库连接、数据清洗和绘图逻辑;推荐pymysql+pandas.read_sql安全取数,显式设置charset='utf8mb4',按需选列,用parse_dates处理日期,聚合去重并补零对齐时间序列,配置中文字体及负号显示,注意时区、类型推断与排序等细节。

直接连 MySQL 取数再画图是可行的,但关键在于避免把数据库连接、数据清洗和绘图逻辑混在一起——否则查个 ConnectionResetError 或 ValueError: x and y must be the same size 就得从头 debug。
用 pymysql + pandas.read_sql 安全取数
别手写 cursor.execute() 拼 SQL,容易漏转义、类型错乱,也难复用。用 pandas.read_sql 一次性读成 DataFrame 最稳:
-
pymysql要显式设charset='utf8mb4',否则中文字段名或值可能变??? - SQL 里别写
SELECT *,只选需要的列(比如sale_date,product_name,amount),减少内存压力和类型推断错误 - 如果日期字段是
DATE或DATETIME,read_sql通常能自动转成datetime64;但若发现是object类型,加参数parse_dates=['sale_date']
画折线图前先确认时间序列是否对齐
销售数据常按日/周聚合,但 MySQL 返回的 sale_date 可能含重复值、空值,或跨多个月份却没补零——直接传给 plt.plot() 会出错或图形跳变:
- 用
df.groupby('sale_date')['amount'].sum().reset_index()强制聚合,避免同一日期多条记录导致线图抖动 - 如果想看连续日期趋势(比如补全周末无销售的空缺),用
df.set_index('sale_date').resample('D').sum().fillna(0).reset_index() - 传给
plt.plot()前,检查len(df['sale_date']) == len(df['amount']),不等说明有NaN没处理干净
中文标签显示不出来?不是字体问题,是 matplotlib 默认禁用
即使系统装了思源黑体,plt.title('销售额趋势') 还是显示方块——因为 Matplotlib 默认不启用中文字体回退:
立即学习“Python免费学习笔记(深入)”;
- 运行一次
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans', 'sans-serif'],注意顺序:Windows 用SimHei,macOS 推荐Heiti TC,Linux 用Noto Sans CJK SC - 必须同时加
plt.rcParams['axes.unicode_minus'] = False,否则负号(如 -100)会变成方块 - 这个设置要放在
import matplotlib.pyplot as plt之后、任何绘图命令之前;放在函数里也行,但别每次画图都重复设
真正卡住人的往往不是语法,而是 MySQL 时间字段时区没对齐、pandas 自动把整数 ID 当成 float、或者画图时用了未排序的原始时间戳——这些细节不打日志根本看不出。


















