2013-07-02 116 views
22

如何獲得忽略NULL和零值的列的AVG獲取AVG忽略空值或零值

我有三列得到他們的平均水平,我嘗試使用下面的腳本:

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 

我沒有得到任何結果,但三列有值,包括NULL和零!

有沒有辦法在得到平均值之前排除空值?

例如:AVERAGE(NOTNULL(SecurityW))

+1

所有這些「AND」表示您只會獲得在所有3列中都具有非空值的行。另外,不需要'NOT NULL'檢查,因爲如果Column是NULL,則Column <> 0評估爲UNKNOWN。 –

回答

1

你已經嘗試過濾掉NOT NULLNULL值。我在WHERE子句中將其更改爲IS NOT NULL,因此它將執行。我們可以通過刪除AVG方法中的ISNULL函數來重構該函數。另外,我懷疑你真的需要bigint,所以我們可以刪除演員。

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

這應該工作,雖然沒有嘗試過。這將排除零。 NULL是默認

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

NULL已經被忽略,所以你可以用NULLIF0NULL排除。你也不需要DISTINCT和你的WHERE在不是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我不知道什麼Table2 b是在原有的查詢,因爲沒有連接條件這麼從我的回答省略了。

+0

btw我不認爲你通過將一個整數轉換爲bigint來實現任何功能 –

+5

@ t-clausen.dk - 如果SUM值過大,它可以防止算術溢出錯誤。 (SELECT)2147483647 UNION ALL SELECT 2147483647)T(C)'失敗,但是'SELECT AVG(CAST(C AS BIGINT))FROM(SELECT 2147483647 UNION ALL SELECT 2147483647)T(C)'成功。 –

+0

我看到你的觀點 –

2

工作對我來說:

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

在案例中不考慮 '0' 或平均函數 'NULL'。 只需使用

AVG(NULLIF(your_column_name,0))