2014-06-17 43 views
2

我有一個查詢如何獲得列值不等於零的平均值?

Select AVG(((cast(c.rating1 as Float)+ cast(c.rating2 as Float)+cast (c.rating3 as Float)+cast(c.rating4 as Float)+cast(c.rating5 as Float))/5)) 
From CSEReduxResponses c 
Where 
    c.execoffice_date BETWEEN DATEADD(MONTH, DATEDIFF(MONTH, 0, @today)-1, 0) 
AND DATEADD(MONTH, DATEDIFF(MONTH, -1, @today)-1, -1) 
AND c.execoffice_status =1 
AND C.rating1 <> 0 AND C.rating2 <> 0 AND C.rating3 <> 0 AND C.rating4 <> 0 AND 
C.rating5 <> 0 

當我得到等級1-5的平均水平,但我還指望收視率,其中等於「0」。

我怎樣才能得到它只能算一個等級,其中等級[X]不等於「0」? 它仍然會計數,除了除以5之外,它會將它除以有多少列不是'0'。

我創建了一個< http://sqlfiddle.com/#!3/570fa/7>

+3

如果您標準化架構你的生活會更容易些:你應該是在它自己的子表中的每個等級在一個單獨的行 – Bohemian

+0

具體表達取決於是否我們保證「重複組」是ratingN永遠是非NULL還是取決於如何處理來自'cast(ratingN As Float)'的NULL值。 – spencer7593

回答

1

嘗試使用VALUES獲得非0值的每一行的平均水平。

SELECT 
(
    SELECT AVG(rating) 
    FROM (VALUES 
     (cast(c.rating1 as Float)), 
     (cast(c.rating2 as Float)), 
     (cast(c.rating3 as Float)), 
     (cast(c.rating4 as Float)), 
     (cast(c.rating5 as Float)) 
    ) AS v(rating) 
    WHERE v.rating <> 0 
) avg_rating 
From CSEReduxResponses c 
Where 
    c.execoffice_date BETWEEN DATEADD(MONTH, DATEDIFF(MONTH, 0, @today)-1, 0) 
AND DATEADD(MONTH, DATEDIFF(MONTH, -1, @today)-1, -1) 
AND c.execoffice_status = 1 

http://sqlfiddle.com/#!3/570fa/26

我從刪除以下條件的WHERE

AND C.rating1 <> 0 AND C.rating2 <> 0 AND C.rating3 <> 0 AND C.rating4 <> 0 AND 
C.rating5 <> 0 

因爲如果你把它留在,你只計算有5個非0評分行平均水平,我猜猜這不是你的意圖。

要在所有行非0評分的總數除以所有非0評分的總和得到非0評分的平均值。

SELECT 
    CAST(SUM(sum_rating) as float)/SUM(count_rating) 
From CSEReduxResponses c 
CROSS APPLY (
    SELECT SUM(rating), COUNT(rating) 
    FROM (VALUES 
     (c.rating1), 
     (c.rating2), 
     (c.rating3), 
     (c.rating4), 
     (c.rating5) 
    ) AS v(rating) 
    WHERE v.rating <> 0 
) AS x (sum_rating, count_rating) 
Where 
    c.execoffice_date BETWEEN DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) 
AND DATEADD(MONTH, DATEDIFF(MONTH, -1, GETDATE())-1, -1) 
AND c.execoffice_status = 1 

http://sqlfiddle.com/#!3/570fa/35

正如其他人所說,你應該考慮如果可能的話你的正常化表。

+1

在第二個查詢中,使用CROSS APPLY [大幅簡化代碼](http://sqlfiddle.com/#!3/570fa/35「SQL小提琴演示」)。 –

+0

@AndriyM更新,謝謝 – FuzzyTree

2

這是不漂亮但應該工作:

SELECT AVG((... SUM of 5 ratings ...)/
      (CASE WHEN rating1 > 0 THEN 1 ELSE 0 END + 
      CASE WHEN rating2 > 0 THEN 1 ELSE 0 END + 
      CASE WHEN rating3 > 0 THEN 1 ELSE 0 END + 
      CASE WHEN rating4 > 0 THEN 1 ELSE 0 END + 
      CASE WHEN rating5 > 0 THEN 1 ELSE 0 END)) 
    FROM ... 
    WHERE ... 

做這樣的事情之一後應該感到讚賞,數據標準化。

+0

看來這個表達式可能不會返回指定的結果NULL或負值爲ratingN。如果我們保證所有的ratingN值都是非空和非負的,這個表達式就行。 (並且在除數爲零的邊緣情況下,MySQL不會拋出「除以零」錯誤;這可能取決於sql_mode的設置。) – spencer7593

+0

@ spencer7593 - 確定。 '當評級不爲零且評級> 0或'當CAOLESCE(評級,0)> 0「時。 OP使用SQL Server 2008,而不是MySql。 –

+0

或者**當等級1 <> 0 ** **就足夠了。 – spencer7593