奇怪的MySQL AVG()异常NULL值

Nis*_*ani 15 mysql sql null

我在做什么 :

create table sample (id INT(10) PRIMARY KEY AUTO_INCREMENT,name varchar(255),marks INT(10));

insert into sample (name,marks) VALUES('sam',10);
insert into sample (name,marks) VALUES('sam',20);
insert into sample (name,marks) VALUES('sam',NULL);
insert into sample (name,marks) VALUES('sam',NULL);
insert into sample (name,marks) VALUES('sam',30);

select AVG(marks) from sample GROUP BY(name);
Run Code Online (Sandbox Code Playgroud)

产出我的预期:

AVG =(10 + 20 + 30)/ 5 = 12

MYSQL的输出:

AVG =(10 + 20 + 30)/ 3 = 20

理想情况下我想要的是MYSQL应该得到5行的总和并除以5,但它只能除以3(非NULL行)

为什么会发生这种情况,我该怎么做才能获得正确的AVG即60/5?PS:我不能使标记字段为NOT NULL,在我的db设计中,标记字段允许为NULL.

谢谢

Kai*_*aii 42

这是正确的行为,因为NULL与数字不同0.

从概念上讲,它NULL意味着"缺失的未知值",并且与其他值的处理方式略有不同.这就是像ignore s 这样的聚合函数.AVG()NULL

AVG()仅计算所有已知值的平均值.(= 不是 NULL =未知)

来自MySQL文档:

除非另有说明,否则组函数会忽略NULL值.

另外,请阅读 MySQL手册"3.3.4.6使用NULL值"一节中NULLs 概念.

为了得到你想要的东西,你可能会这样做

SELECT AVG(IFNULL(marks, 0)) FROM sample GROUP BY(name);
Run Code Online (Sandbox Code Playgroud)

IFNULL()如果值为NULL或通过该值,则返回计算的第二个参数.


关于概念存在更多常见的误解NULL.这些也在本手册的"5.5.3 NULL的问题"一节中进行了解释:

  • 在SQL中,与任何其他值相比,"NULL"值永远不会为真,即使是"NULL".包含"NULL"的表达式总是产生一个"NULL"值,除非在文档中为表达式中涉及的运算符和函数另有说明.

    ie:`NULL == 0`导致NULL而不是`true`."NULL == NULL"也会导致NULL,而不是true.
  • 要搜索"NULL"的列值,不能使用`expr = NULL`测试.要查找"NULL"值,必须使用`IS NULL`测试.
  • 当使用`DISTINCT`,`GROUP BY`或`ORDER BY`时,所有`NULL`值都被视为相等.
  • 使用`ORDER BY`时,首先显示`NULL`值,如果指定`DESC`按降序排序则返回最后一个值.
  • 对于某些数据类型,MySQL特别处理NULL值.如果在`TIMESTAMP`列中插入`NULL`,则插入当前日期和时间.
  • 如果将"NULL"插入到具有"AUTO_INCREMENT"属性的整数或浮点列中,则插入序列中的下一个数字.
  • 定义了"UNIQUE"键的列仍然可以包含多个"NULL"值.


fge*_*fge 5

尝试:

select avg(case marks when null then 0 else marks end) from sample group by name;
Run Code Online (Sandbox Code Playgroud)

或者尝试避免表中出现空值;)