我有简单的表格,例如:
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
哪种查询性能更好?还有其他解决方案吗?
答案 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
如果您正在使用其他数据库引擎,我不知道如何向您展示执行计划,但大多数人都有办法实现这一目标。
注意:我不知道更快的方法,但这并不意味着没有。