当存在null时,SQL查询返回null而不是SUM

时间:2013-10-24 18:39:05

标签: sql performance

我有简单的表格,例如:

create table #test(x int, y int)
insert into #test values(null, 1)
insert into #test values(1, 1)
insert into #test values(1, 2)
insert into #test values(2, 2)
insert into #test values(3, 2)

我需要通过分组获得总和,但如果组具有空值,则获取null而不是sum。 我可以用两个查询来做到这一点:

1) select y, case when AVG(x)<>SUM(x)/COUNT(*) then null else SUM(x) end from #test
group by y
2) select y, CASE WHEN EXISTS(select * from #test innerTest where innerTest.y=outerTest.y and x is null) then null else sum(x) end 
from #test outerTest group by y

哪种查询性能更好?还有其他解决方案吗?

2 个答案:

答案 0 :(得分:6)

你可以检查组是否有这样的空值:

select
    y,
    case when count(x) <> count(*) then null else sum(x) end
from test
group by y

<强> sql fiddle demo

我99.99%肯定这个会跑得比子查询更快。

答案 1 :(得分:1)

第一个选项运行得更快。 2示例中的EXETS时的情况将需要在第一个示例中不需要的附加表扫描。如果您使用的是SQL Server,则可以在查询计划中看到这一点。

以下是执行上述语句的TSQL代码,如果您使用的是SQL服务器,则会在结果中显示执行计划:

CREATE TABLE #test ( x INT, y INT )
INSERT  INTO #test VALUES  ( NULL, 1 )
INSERT  INTO #test VALUES  ( 1, 1 )
INSERT  INTO #test VALUES  ( 1, 2 )
INSERT  INTO #test VALUES  ( 2, 2 )
INSERT  INTO #test VALUES  ( 3, 2 )
GO

SET STATISTICS PROFILE  ON
GO

SELECT  y ,
        sumG = CASE WHEN AVG(x) <> SUM(x) / COUNT(*) THEN NULL
                    ELSE SUM(x)
               END
FROM    #test
GROUP BY y
ORDER BY y ,
        SUM(X) DESC

SELECT  y ,
        sumG = CASE WHEN EXISTS ( SELECT    *
                                  FROM      #test innerTest
                                  WHERE     innerTest.y = outerTest.y
                                            AND x IS NULL ) THEN NULL
                    ELSE SUM(x)
               END
FROM    #test outerTest
GROUP BY y
ORDER BY y ,
        SUM(X) DESC
GO

SET STATISTICS PROFILE  OFF
GO

DROP TABLE #test;
GO

如果您正在使用其他数据库引擎,我不知道如何向您展示执行计划,但大多数人都有办法实现这一目标。

注意:我不知道更快的方法,但这并不意味着没有。