19

我在做什么 :

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);

我预期的输出:

平均数 = (10+20+30)/5 = 12

MYSQL 的输出:

平均数 = (10+20+30)/3 = 20

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

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

谢谢

4

5 回答 5

55

这是正确的行为,因为NULL与 number 不同0
这可能会让一些不会说英语的人感到惊讶,因为在许多语言中“null”等同于“zero”。

从概念上讲,NULL指的是“未知值”,因此它的处理方式与其他值不同。这就是为什么像ignore s这样的聚合函数。AVG()NULL

AVG()仅计算所有“已知”值的平均值。(=为NULL)

来自MySQL 文档

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

另外,请阅读 MySQL 手册的“3.3.4.6 使用 NULL 值”部分NULL中的s概念。

为了得到你想要的,你可能会做

SELECT AVG(IFNULL(marks, 0)) 
FROM sample 
GROUP BY name;

IFNULL()NULL如果该值是或通过该值,则返回用于计算的第二个参数。


关于NULL. 这些也在手册的“5.5.3 NULL问题”部分中进行了解释:

  • 在 SQLNULL中,与任何其他值(甚至NULL. 除非在文档中针对表达式中涉及的运算符和函数另有说明,否则包含的表达式NULL始终会产生一个值。即:导致 NULL 而不是. 也会导致 NULL,而不是 true。NULL

    NULL == 0trueNULL == NULL
  • 要搜索为 的列值NULL,您不能使用expr = NULL测试。要查找NULL值,您必须使用IS NULL测试。
  • 使用DISTINCTGROUP BYORDER BY时,所有NULL值都被视为相等。
  • 使用 时ORDER BYNULL首先显示值,如果您指定DESC按降序排序,则最后显示值。
  • 对于某些数据类型,MySQL 专门处理 NULL 值。如果插入NULLTIMESTAMP,则插入当前日期和时间。
  • 如果您插入NULL到具有该属性的整数或浮点列中,AUTO_INCREMENT则会插入序列中的下一个数字。
  • 定义了键的列UNIQUE仍然可以包含多个NULL值。
于 2012-12-24T11:43:02.043 回答
3

尝试:

select avg(case marks when null then 0 else marks end) from sample group by name;

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

于 2012-12-24T11:43:11.893 回答
2

你可以这样做:

SELECT SUM(marks) / COUNT(name)
FROM sample 
GROUP BY name;
于 2012-12-24T11:44:57.713 回答
1

这是正常行为,因为 NULL 不为零。你如何使 5 + NULL 的平均值?所以 MySQL 只取可以平均的行。

除了其他用户已经给您的正确答案之外,您还可以使用 COALESCE 函数,该函数返回您在列表中指定的第一个非 NULL 值,因此您可以将 NULL 替换为您喜欢的值:

    SELECT AVG(COALESCE(marks,0)) FROM sample GROUP BY(name);
于 2012-12-24T11:58:54.160 回答
0
SELECT
       avg(CASE WHEN price IS NULL THEN 0 else price END), 
       avg(CASE WHEN discount IS NULL THEN 0 else discount END), 
       avg(CASE WHEN total IS NULL THEN 0 else total END) 
FROM pet;
于 2019-03-11T05:12:39.740 回答