2013-07-02 9 views
22

Jak mogę uzyskać AVG kolumny ignorującej NULL i wartości zerowych?Otrzymuj AVG ignorując wartości Null lub Zero

mam trzy kolumny, aby uzyskać ich średnią, staram się wykorzystać następujący skrypt:

SELECT distinct 
    AVG(cast(ISNULL(a.SecurityW,0) as bigint)) as Average1 
    ,AVG(cast(ISNULL(a.TransferW,0) as bigint)) as Average2 
    ,AVG(cast(ISNULL(a.StaffW,0) as bigint)) as Average3 
FROM Table1 a, Table2 b 
WHERE a.SecurityW <> 0 AND a.SecurityW IS NOT NULL 
AND a.TransferW<> 0 AND a.TransferWIS NOT NULL 
AND a.StaffW<> 0 AND a.StaffWIS NOT NULL 
AND MONTH(a.ActualTime) = 4 
AND YEAR(a.ActualTime) = 2013 

nie dostać żadnych wyników, jednak trzy kolumny mają wartości NULL i tym zerami!

Czy mimo to można wykluczyć wartości puste przed uzyskaniem średniej?

przykład: AVERAGE(NOTNULL(SecurityW))

+1

Wszystkie te 'AND's oznacza, że ​​dostaniesz tylko wiersze, które mają wartości non-NULL we wszystkich 3 kolumn. Ponadto, twoje sprawdzenia "NOT NULL" nie są wymagane, ponieważ 'Column <> 0' ma wartość' UNKNOWN', jeśli 'Column' ma wartość' NULL'. –

Odpowiedz

1

Już próbować odfiltrować NULL wartości z NOT NULL. Zmieniłem to na IS NOT NULL w klauzuli WHERE, aby zostało wykonane. Możemy to zmienić, usuwając funkcję ISNULL w metodzie AVG. Ponadto wątpię, czy będziesz potrzebować bigint, abyśmy mogli usunąć rzutowanie.

SELECT distinct 
    AVG(a.SecurityW) as Average1 
    ,AVG(a.TransferW) as Average2 
    ,AVG(a.StaffW) as Average3 
FROM Table1 a, Table2 b 
WHERE a.SecurityW <> 0 AND a.SecurityW IS NOT NULL 
AND a.TransferW<> 0 AND a.TransferWIS IS NOT NULL 
AND a.StaffW<> 0 AND a.StaffWIS IS NOT NULL 
AND MONTH(a.ActualTime) = 4 
AND YEAR(a.ActualTime) = 2013 
7

to powinno zadziałać, nie próbowałem jednak. to wyklucza zero. NULL jest wyłączone domyślnie

AVG (CASE WHEN SecurityW <> 0 THEN SecurityW ELSE NULL END) 
43

NULL jest już ignorowany, dzięki czemu można używać NULLIF włączyć 0 do NULL. Również nie potrzebujesz DISTINCT, a Twoja WHERE na nie jest sowita.

SELECT AVG(cast(NULLIF(a.SecurityW, 0) AS BIGINT)) AS Average1, 
     AVG(cast(NULLIF(a.TransferW, 0) AS BIGINT)) AS Average2, 
     AVG(cast(NULLIF(a.StaffW, 0) AS BIGINT)) AS Average3 
FROM Table1 a 
WHERE a.ActualTime >= '20130401' 
     AND a.ActualTime < '20130501' 

PS Nie mam pojęcia, co Table2 b jest w pierwotnym zapytaniu tak tam nie ma dołączyć warunek, że tak nie pominięto go z moją odpowiedź.

+0

btw Nie sądzę, abyś cokolwiek zrobił, konwertując liczbę całkowitą na biginta –

+5

@ t-clausen.dk - Może to zapobiec błędowi przepełnienia arytmetycznego, jeśli 'SUMA' jest zbyt duże. 'WYBIERZ AVG (C) Z (WYBIERZ 2147483647 UNION ALL SELECT 2147483647) T (C)' zawiedzie, ale 'WYBIERZ AVG (CAST (C AS BIGINT)) OD (SELECT 2147483647 UNION ALL SELECT 2147483647) T (C)' powiedzie się. –

+0

Widzę twój punkt –

2

pracował dla mnie:

AVG(CASE WHEN SecurityW <> 0 THEN SecurityW ELSE NULL END) 
0

w przypadku braku uwzględnienia '0' lub 'NULL' przeciętnego funkcji. Wystarczy użyć

AVG(NULLIF(your_column_name,0)) 
Powiązane problemy