2012-12-24 19 views
12

ne I'am durumu:Garip MySQL AVG() anomali NULL değerleri

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

ÇIKIŞ BEKLEDİĞİMDEN:

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

MYSQL OF

ÇIKIŞ:

AVG = (10 + 20 + 30)/3 = i MYSQL 5 satır toplamını almak ve 5. bölerek, ancak yalnızca 3 ile böler gerektiğidir istediğini İdeal neyi 20

(NULL olmayan satırlar)

Neden böyle oluyor ve doğru AVG'yi elde etmek için ne yapabilirim? PS: İşaretleri alan yapamam NULL, db tasarımımda işaretler alanının NULL olmasına izin verilir. NULL numara 0 aynı değildir çünkü

, sizi

+1

i mySQL gibi =/(nos sütunların toplamı AVG gerçekleştirilen izlenim oldu, bu çözüm yardımcı benim cevaba :) – Kaii

+0

sayesinde @Kaii daha açıklama ve referanslar eklendi sonuçta) –

cevap

33

Bu doğru bir davranıştır ederiz. Kavramsal olarak, NULL, "bilinmeyen bir eksik değer" anlamına gelir ve diğer değerlerden biraz farklı şekilde ele alınır. Bu nedenle,AVG(), NULL s'yi göz ardı eder.

AVG(), yalnızca belirtilen değerlerinin ortalamasını hesaplar. (değil NULL olan =) MySQL docs itibaren

: Aksi belirtilmedikçe

, grup fonksiyonları NULL değerleri görmezden.

Ayrıca MySQL kılavuzun Section "3.3.4.6 Working with NULL Values" içinde NULL s kavramı hakkında okuyun.

sen, değeri NULL veya başka türlü değerin geçiyorsa

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

IFNULL() hesaplamalar için ikinci argüman döner yapabilir istediğini elde etmek.


NULL kavramı konusunda en sık rastlanan yanlış anlamalar vardır. Bunlar da kılavuzun Section "5.5.3 Problems with NULL" açıklanmıştır: SQL

  • , `NULL` değeri başka bir değerle karşılaştırıldığında bile` NULL` asla doğru değildir. 'NULL' içeren bir ifade, ifadede yer alan işleçler ve işlevler için aksi belirtilmedikçe her zaman bir "NULL" değeri üretir.

    i.e.: `NULL == 0`` true` yerine NULL ile sonuçlanır. Ayrıca 'NULL == NULL', true yerine NULL ile sonuçlanır.
  • "NULL" olan sütun değerlerini aramak için bir "expr = NULL" testi kullanamazsınız. `NULL` değerlerini aramak için` IS NULL` testini kullanmalısınız.
  • `DISTINCT`,` GROUP BY` veya `ORDER BY` kullanılırken, tüm` NULL` değerleri eşit olarak kabul edilir.
  • `ORDER BY` kullanıldığında, önce" NULL "değerleri sunulur veya azalan sırada sıralamak için" DESC "ifadesini belirtirseniz devam eder.
  • Bazı veri türleri için MySQL NULL değerlerini özel olarak işler. `NULL 'bir` TIMESTAMP` sütununa eklerseniz, geçerli tarih ve saat eklenir.
  • Eğer 'NULL', 'AUTO_INCREMENT' özelliğine sahip bir tamsayıya veya kayan nokta sütununa eklerseniz, sıradaki sonraki numara eklenir.
  • `UNIQUE` anahtarının tanımlanmış bir sütunu hala birden çok 'NULL' değeri içerebilir.
+0

sayesinde @kaii yardımcı –

2

Dene:

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

Veya denemek ve tablodaki boş değerlere kaçınmak;) Bunun yerine bunu yapabilirsiniz

+0

yardım @fge için teşekkürler –

1

:

NULL beri normal davranışı var
SELECT SUM(marks)/COUNT(name) 
FROM sample 
GROUP BY name; 
1

sıfır değil. 5 + NULL'un ortalamasını nasıl yaparsınız? Yani MySQL sadece ortalamaları alınabilen satırları alıyor.

Diğer kullanıcıların size verdikleri doğru yanıtlardan yararlanarak, listede belirttiğiniz ilk NULL olmayan değeri döndüren COALESCE işlevini de kullanabilirsiniz, böylece NULL birini istediğiniz gibi değiştirebilirsiniz :

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