2012-12-24 35 views
12

gì I'am thực hiện:Strange MySQL AVG() giá trị bất thường 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); 

OUTPUT Tôi DỰ KIẾN:

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

OUTPUT của MySQL:

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

Lý tưởng nhất là những gì tôi muốn là MYSQL sẽ nhận được tổng số 5 hàng và chia cho 5, nhưng nó chỉ chia bởi 3 (hàng không NULL)

Tại sao điều này xảy ra và tôi có thể làm gì để có được đúng AVG tức là 60/5? PS: Tôi không thể tạo trường đánh dấu NOT NULL, trong thiết kế db của tôi trường đánh dấu được phép là NULL.

Cảm ơn bạn

+1

thêm nhiều hơn lời giải thích và tài liệu tham khảo câu trả lời của tôi – Kaii

+0

nhờ @Kaii đã giúp :) –

Trả lời

33

Đây là hành vi đúng, bởi vì NULL không giống như số 0.

Khái niệm, NULL có nghĩa là "thiếu giá trị không xác định" và được xử lý hơi khác so với các giá trị khác. Đó là lý do tại sao aggregate functions như AVG() bỏ qua NULL s.

AVG() tính giá trị trung bình trên tất cả chỉ định giá trị. (= Có không NULL)

Từ MySQL docs:

Trừ khi có quy định khác, các chức năng nhóm bỏ qua các giá trị NULL.

Ngoài ra, hãy đọc về khái niệm NULL s trong Section "3.3.4.6 Working with NULL Values" của hướng dẫn sử dụng MySQL.

Để có được những gì bạn muốn, bạn có thể làm

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

IFNULL() trả về số thứ hai để tính toán nếu giá trị là NULL hoặc đi qua các giá trị khác.


Có nhiều hiểu lầm phổ biến hơn về khái niệm NULL. Đây cũng được giải thích trong Section "5.5.3 Problems with NULL" của cuốn cẩm nang:

  • Trong SQL, 'cái giá trị NULL` là không bao giờ thành sự thật so với bất kỳ giá trị khác, ngay cả' NULL`. Một biểu thức có chứa `NULL` luôn luôn tạo ra một giá trị` NULL` trừ khi được chỉ rõ trong tài liệu cho các toán tử và các hàm liên quan đến biểu thức.

    tức là: `NULL == 0` dẫn đến NULL thay vì` true`. Ngoài ra `NULL == NULL` kết quả bằng NULL, thay vì đúng.
  • Để tìm kiếm các giá trị cột là `NULL`, bạn không thể sử dụng phép thử` expr = NULL`. Để tìm các giá trị `NULL`, bạn phải sử dụng phép thử` IS NULL`.
  • Khi sử dụng `DISTINCT`,` GROUP BY` hoặc `ORDER BY`, tất cả giá trị` NULL` được coi là bằng nhau.
  • Khi sử dụng giá trị `ORDER BY`,` NULL` được hiển thị trước tiên hoặc cuối cùng nếu bạn chỉ định `DESC` để sắp xếp theo thứ tự giảm dần.
  • Đối với một số loại dữ liệu, MySQL xử lý các giá trị NULL một cách đặc biệt. Nếu bạn chèn `NULL` vào cột` TIMESTAMP`, ngày và thời gian hiện tại được chèn vào.
  • Nếu bạn chèn `NULL` vào một số nguyên hoặc cột dấu phẩy động có thuộc tính` AUTO_INCREMENT`, số tiếp theo trong chuỗi được chèn vào.
  • Cột có khóa `UNIQUE` được xác định vẫn có thể chứa nhiều giá trị` NULL`.
+0

nhờ @kaii, giải pháp mà giúp, tôi đã theo ấn tượng mySQL thực hiện AVG như = sum/(nos của cột trong kết quả) –

2

Hãy thử:

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

Hoặc thử và tránh null trong bảng;)

+0

cảm ơn vì sự giúp đỡ @fge –

1

Bạn có thể làm điều này thay vì:

SELECT SUM(marks)/COUNT(name) 
FROM sample 
GROUP BY name; 
1

Đó là hành vi bình thường, vì NULL không phải là số không. Làm thế nào để bạn thực hiện trung bình của 5 + NULL? Vì vậy, MySQL chỉ lấy các hàng có thể được tính trung bình. Bạn có thể sử dụng hàm COALESCE, trả về giá trị không NULL đầu tiên mà bạn chỉ định trong danh sách, vì vậy bạn có thể thay thế giá trị NULL bằng cái bạn thích :

SELECT AVG(COALESCE(marks,0)) FROM sample GROUP BY(name); 
Các vấn đề liên quan