2014-03-03 14 views
2

每一個問題,我搜索有關的警告更改聚合函數輸出空當元素爲null

警告:Null值由聚合或其它SET操作消除。

通常人們想將NULL值視爲0.我想相反,如何修改以下存儲過程以使其返回NULL而不是1?

CREATE PROCEDURE TestProcedure 
AS 
BEGIN 
select cast(null as int) as foo into #tmp 

insert into #tmp values (1) 

select sum(foo) from #tmp 
END 
GO 

我認爲這將是SET ANSI_NULLS ON(我的聲明之前試過了,過程內,在我的測試查詢執行過程之前),但並沒有出現改變的SUM(行爲。

+2

所以要聚合函數返回空值,如果集合中的任何元素爲null? –

回答

6

sum()功能自動忽略NULL。做你想做什麼,你需要一個明確的檢查:

select (case when count(foo) = count(*) then sum(foo) end) 
from #tmp; 

如果你想成爲明確的,你可以添加else NULLcase聲明。

這背後的邏輯是count(foo)計數foo中的非NULL值的數量。如果這等於所有的行,那麼所有的值都是非空的。你可以使用更詳細的:

select (case when sum(case when foo is null then 1 else 0 end) > 0 
      then sum(foo) 
     end) 

而且,我想指出,標題是相當誤導。 1 + NULL = NULL。問題在於聚合函數,而不是算術運算符。

+0

由於計數兩次,是否會對大型表造成較大的性能損失? –

+0

'EXISTS'會更快嗎? –

+0

@ScottChamberlain。 。 。你可能不會注意到性能的差異。查詢的大部分時間將循環遍歷數據頁面並從磁盤獲取它們。與此相比,'count()'應該是較小的開銷。 –

2

尋找與EXISTS空值可能是最快的:

SELECT 
    CASE WHEN EXISTS(SELECT NULL FROM tmp WHERE foo IS NULL) 
     THEN NULL 
     ELSE (SELECT sum(foo) from tmp) 
    END 
0

只是說

select case sign(sum(case when foo is null then 1 else 0 end)) 
     when 1 then null 
     else  sum(foo) 
     end 
from some_table 
... 
group by 
... 

這是對你所需要的。