2013-07-02 42 views
22

Làm cách nào để nhận được AVG của cột bỏ qua NULL và giá trị bằng không?Nhận AVG bỏ qua giá trị Null hoặc Zero

Tôi có ba cột để có được trung bình của họ, tôi cố gắng sử dụng các kịch bản sau đây:

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 

tôi không nhận được bất kỳ kết quả, tuy nhiên ba cột có giá trị bao gồm NULL và số không!

Có cách nào để loại trừ giá trị null trước khi nhận giá trị trung bình không?

dụ: AVERAGE(NOTNULL(SecurityW))

+1

Tất cả những điều đó có nghĩa là bạn sẽ chỉ nhận các hàng có giá trị không NULL trong cả 3 cột. Ngoài ra, kiểm tra 'NOT NULL' của bạn không bắt buộc, vì' Column <> 0' đánh giá là 'UNKNOWN' nếu' Column' là 'NULL'. –

Trả lời

1

Bạn đã cố gắng để lọc ra NULL giá trị với NOT NULL. Tôi đã thay đổi điều này thành IS NOT NULL trong mệnh đề WHERE để nó sẽ thực thi. Chúng ta có thể cấu trúc lại nó bằng cách loại bỏ hàm ISNULL trong phương thức AVG. Ngoài ra, tôi nghi ngờ bạn sẽ thực sự cần bigint để chúng tôi có thể xóa dàn diễn viên.

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

điều này sẽ hoạt động, chưa thử. điều này sẽ loại trừ bằng không. NULL được loại trừ theo mặc định

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

NULL đã được bỏ qua, do đó bạn có thể sử dụng để biến NULLIF0-NULL. Ngoài ra, bạn không cần DISTINCTWHERE trên của bạn không được sargable.

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 Tôi không có ý tưởng gì Table2 b là trong truy vấn ban đầu cho là không có điều kiện join cho nó nên đã bỏ qua nó từ câu trả lời của tôi.

+0

btw Tôi không nghĩ rằng bạn làm bất cứ điều gì bằng cách chuyển đổi một số nguyên thành bigint –

+5

@ t-clausen.dk - Nó có thể ngăn chặn lỗi tràn số học nếu 'SUM' quá lớn. 'SELECT AVG (C) TỪ (SELECT 2147483647 UNION ALL SELECT 2147483647) T (C)' không thành công nhưng 'SELECT AVG (CAST (C AS BIGINT)) TỪ (SELECT 2147483647 UNION ALL SELECT 2147483647) T (C)' thành công. –

+0

Tôi thấy điểm của bạn –

2

làm việc cho tôi:

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

Trong trường hợp không xem xét '0' hoặc 'NULL' trong chức năng trung bình. Chỉ cần sử dụng

AVG(NULLIF(your_column_name,0)) 
Các vấn đề liên quan