我有两种解决方案,可以找到正整数和负整数的总和。请告诉哪个更正确,更优化? 还是还有其他更优化,更正确的查询? 问:
考虑表A的col1及以下值。
col1
20
-20
40
-40
-30
30
我需要下面的输出
POSITIVE_SUM NEGATIVE_SUM
90 -90
我有两种解决方法。
/ q1 /
select POSITIVE_SUM,NEGATIVE_SUM from
(select distinct sum(a2.col1) AS "POSITIVE_SUM" from A a1 join A a2 on a2.col1>0
group by a1.col1)
t1
,
(select distinct sum(a2.col1) AS "NEGATIVE_SUM"from A a1 join A a2 on a2.col1<0
group by a1.col1) t2;
/ q2 /
select sum (case when a1.col1 >= 0 then a1.col1 else 0 end) as positive_sum,
sum (case when a1.col1 < 0 then a1.col1 else 0 end) as negative_sum
from A a1;
POSITIVE_SUM NEGATIVE_SUM
90 -90
答案 0 :(得分:3)
我想知道您是如何提出第一个解决方案的:
-自联接(两次)表,
-每次产生6
(相同)行,最后通过distinct
得到1行,
-然后交叉加入2个结果。
我准备了demo,以便您看到导致第一个解决方案结果的步骤。
我不知道是否可以通过任何方式对其进行优化,
但是否有可能像第二种解决方案那样用条件聚合击败表的单次扫描?
我不这么认为。
答案 1 :(得分:2)
第二个查询不仅性能更好,而且返回正确的值。如果您运行第一个查询,则会看到它返回多行。
我认为对于第一个查询,您正在寻找类似的东西:
select p.positive_sum, n.negative_sum
from (select sum(col1) as positive_sum from a1 where col1 > 0) p cross join
(select sum(col1) as negative_sum from a1 where col1 < 0) n
您要问的case
表达式要比where
快。
您缺少的是该版本需要扫描表两次。读取数据通常比数据元素上的任何功能都要昂贵。
有时第二个查询的性能可能非常相似。我可以想到三种情况。首先是col1
上有聚集索引。其次是将col1
用作分区键。第三是关于非常少量的数据(例如,适合单个数据页面的数据)。