2017-05-30 43 views
0

我正在使用SQL Server。 我有表,在不同的任務時間價值和天從1到7,像這樣(表TaskHours):SQL Server - 無法選擇Sum> 0的行0

 | TaskID | Hours1 | Hours2 | Hours3 | Hours4 | Hours5 | Hours6 | Hours7 | 
     | 1  | NULL | 10  | NULL | NULL | NULL | NULL | NULL | 
     | 2  | NULL | NULL | 0  | NULL | NULL | NULL | NULL | 
     | 3  | 0  | NULL | 0  | NULL | 0  | 0  | NULL | 
     | 4  | 3  | 3  | 0  | 3  | NULL | NULL | 3  | 
     | 5  | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 

我只需要計算時間的總和爲每個的TaskID,只有有選擇那些在他們的小時的總和> 0 但是,當我嘗試寫:

SELECT TaskID, Hours1, Hours2, Hours3, Hours4, Hours5, Hours6, Hours7, 
     SUM(ISNULL(Hours1, 0) + ISNULL(Hours2, 0) + ISNULL(Hours3, 0) + ISNULL(Hours4, 0) 
     + ISNULL(Hours5, 0) + ISNULL(Hours6, 0) + ISNULL(Hours7, 0)) AS TotalHours 
    FROM TaskHours 
    WHERE TotalHours > 0 

然後我得到的錯誤:

Invalid column name 'TotalHours'. 

什麼我做錯了,以及如何修理它?

+0

這是SQL Server [邏輯處理順序](https://destinationdata.wordpress.com/2016/01/10/the-logical-processing-order-3/)的結果。 TL/DR:select子句中的別名僅適用於order by。交叉應用和子查詢可以解決這個問題。 –

回答

4

您可以在子查詢中使用如下

SELECT * from (
    SELECT TaskID, Hours1, Hours2, Hours3, Hours4, Hours5, Hours6, Hours7, 
    ISNULL(Hours1, 0) + ISNULL(Hours2, 0) + ISNULL(Hours3, 0) + ISNULL(Hours4, 0) 
    + ISNULL(Hours5, 0) + ISNULL(Hours6, 0) + ISNULL(Hours7, 0) AS TotalHours 
    FROM TaskHours ) a 
WHERE a.TotalHours > 0 
+0

非常感謝。 –

+1

對於這個簡單的例子,子查詢可能沒問題。但值得注意的是,對於數據庫來說,從性能的角度來看,通常值得咬住子彈並將複雜的選擇表達式複製/粘貼到where或group by子句中。然後再去洗個澡,因爲你覺得這樣重複的代碼太髒了。 –

+0

困難來自模式未規範化的事實。在只有一個「小時」列的子表(1:n)中設置小時將允許我們用'GROUP BY TaskID'編寫一個簡單的'SELECT SUM(小時)'。 –

2

據我瞭解,問題是TotalHours還是當你寫的WHERE條款不存在。

因此,這裏是我的解決方案:

SELECT * FROM(
SELECT TaskID, Hours1, Hours2, Hours3, Hours4, Hours5, Hours6, Hours7, 
     (IFNULL(Hours1, 0) + IFNULL(Hours2, 0) + IFNULL(Hours3, 0) + IFNULL(Hours4, 0) + IFNULL(Hours5, 0) + IFNULL(Hours6, 0) + IFNULL(Hours7, 0)) 
     AS TotalHours FROM taskhours) as res WHERE res.TotalHours > 0; 

讓我解釋一下。這被稱爲子查詢。查詢內部是查詢。 如果您閱讀我剛剛發佈的代碼,您會注意到以下結構。

SELECT * FROM (subquery) as fooName WHERE fooName.foo = 'something'; 

這個結構強制'子查詢'在外部結構被調用之前被完全解析。所以你的情況:

SELECT * FROM(subquery) as res WHERE res.TotalHours > 0; 

現在TotalHours存在,因爲 '子查詢' 有

(IFNULL(Hours1, 0) + IFNULL(Hours2, 0) + IFNULL(Hours3, 0) + IFNULL(Hours4,0) + IFNULL(Hours5, 0) + IFNULL(Hours6, 0) + IFNULL(Hours7, 0)) AS TotalHours 

已得到解決。

另一件事。我刪除了SUM()因爲你說:

"since I need just calculate the sum of hours for each TaskID and select only those of them that has the Sum of hours > 0."

SUM()實際上將總結您的輸出的所有行的離開你總學時所有TaskID的在一個單行像這樣所有的結果:

With SUM()

並以我的理解,你需要這樣的事: Without SUM()

最後:IFNULL()相當於MYSQL中的ISNULL()