AVG()是MySQL中计算数值列平均值的聚合函数,只接受INT、FLOAT、DECIMAL等数值类型列,自动忽略NULL值;若整列均为NULL则返回NULL而非0,不支持字符串或日期列直接计算。
AVG() 只接受数值类型列,对 NULL 值自动忽略——这点很关键,不是报错,而是静默跳过。如果整列都是 NULL,结果返回 NULL,不是 0。
最常用写法是:SELECT AVG(price) FROM products;。注意不能写成 AVG(*) 或 AVG(name),否则会报错 ERROR: function avg(character varying) does not exist(PostgreSQL)或类似提示(MySQL/SQL Server 各有不同但都拒绝非数值类型)。
AVG(CAST(created_at AS DATE)) 没有意义,得转成时间戳差值再算NULL 当 0 处理?不行,AVG 不支持内置的“空值填充”,得用 COALESCE(price, 0) 包一层,但逻辑已改变(此时算的是“把 NULL 当 0 后的均值”,不是真实业务含义)GROUP BY,整张表只出一行结果;加了 GROUP BY category,就按分类各算一个平均值单独看 AVG(salary) 可能误导。比如结果是 8500,但实际可能只有 2 条非空记录,其余 98 行全是 NULL——这说明数据缺失严重。
推荐每次用 AVG() 时顺手加一列:COUNT(salary) 和 COUNT(*) 对比:
SELECT AVG(salary) AS avg_salary, COUNT(salary) AS non_null_count, COUNT(*) AS total_rowsFROM employees;
如果 non_null_count 远小于 total_rows,就得查清洗逻辑或上游录入问题,而不是直接拿平均值做报表。
AVG() 的返回类型取决于输入列:如果原列是 INT,多数数据库(如 PostgreSQL)仍返回 NUMERIC 或 DOUBLE PRECISION,但 MySQL 在某些旧版本中可能截断小数位。
ROUND(AVG(score), 2) 确保两位小数,避免前端展示出现 89.33333333333333
AVG(score * 1.0)(SQL Server),或用 AVG(CAST(score AS DECIMAL(10,2)))(PostgreSQL/MySQL)AVG(CASE WHEN status='active' THEN salary END) 是对的;错误写法 AVG(salary) WHERE status='active' 语法直接报错想看每个员工工资比部门平均高多少?别用子查询关联,直接上窗口函数:AVG(salary) OVER (PARTITION BY dept_id)。
这样一行语句就能同时拿到个体值和群体基准:
SELECT name, salary, AVG(salary) OVER (PARTITION BY dept_id) AS dept_avg_salary, salary - AVG(salary) OVER (PARTITION BY dept_id) AS diff_from_dept_avgFROM employees;
注意:窗口版 AVG() 仍跳过 NULL,且 PARTITION BY 分组内若全为 NULL,对应行的 dept_avg_salary 也是 NULL。没有 ORDER BY 子句时,默认是整分组全量计算,不是累积平均。
真正容易被忽略的是:AVG() 在 GROUP BY 和窗口函数中行为一致(都跳 NULL),但语义完全不同——前者压缩行数,后者保持原行数。混用时务必确认你到底要聚合还是对标。