使用SUM()两次不是最佳选择?


8

我知道我必须写SUM两次,如果我想在HAVING子句中使用它(否则要使用派生表):

SELECT  id,
  sum(hours) AS totalhours
  FROM mytable
  GROUP BY id
  HAVING sum(hours) > 50;

我现在的问题是,这是否不是最理想的。作为程序员,该查询看起来像数据库将两次计算总和。是这样,还是我应该依靠数据库引擎为我做的优化?

更新:对类似查询的解释:

postgres=> explain select sum(counttodo) from orderline group by orderlineid having sum(counttodo) > 100;
                             QUERY PLAN                             
--------------------------------------------------------------------
 HashAggregate  (cost=1.31..1.54 rows=18 width=8)
   Filter: (sum(counttodo) > 100)
   ->  Seq Scan on orderline  (cost=0.00..1.18 rows=18 width=8)
(3 rows)

你可以发表解释吗?
Ste

因为有一个很好的,简洁的解释,我不会回答这个问题在这里:“如果你想知道为什么你不能在WHERE子句中的查询是指在SELECT别名后一样,这一切都与顺序执行SQL不会按其编写的顺序进行评估。SELECT-list实际上几乎是最后评估的,并且在处理HAVING等时实际上还不存在其内容。当select-list包含带有副作用[“]
dezso

...这就是为什么您不能仅在HAVING子句中引用聚合列的原因-但据我所知,在内部这是相反的方法。
dezso

2
@BartFriederichs好吧,很多人在这些行旁边抱怨(我也曾抱怨过,直到我不习惯它为止……)它没有执行两次,可能可以通过使用别名来实现HAVING(然后提取列定义)从SELECT子句)-由于某种原因,他们只是不这样做。
dezso

3
我认为让数据库引擎担心优化应该是RDBMS实践者的第二天性。SQL是4GL,因此我们要定义所需的结果集,而不是实现它的方法。我们还有很多其他问题我们不必担心,例如连接顺序或将EXISTS转换为连接。从“不要重复自己”的角度讲,对于复杂的表达,这个特定问题更是一个问题,但是明智的解决方法(内联视图,CTE)可以帮助解决这些问题。
大卫·奥尔德里奇

Answers:


3

该和仅计算一次。

我使用

create table mytable (id int, hours int);
insert into mytable values (1, 60);
select sum(hours) from mytable group by id having sum(hours) > 50;

然后使用调试器检查int4_sum调用了几次(sum聚合后面的转换函数):一次。


0

比较您的查询

explain
select sum(counttodo)
from orderline
group by orderlineid
having sum(counttodo) > 100

与此等同的人检查一下它们的区别

explain
select *
from (
    select sum(counttodo) counttodo
    from orderline
    group by orderlineid
) s
where counttodo > 100

1
我可以看到您正在得到什么,但是按照目前的形式,这并不是一个“好”答案。为每个评论发布解释并添加一些评论,这样对您有所帮助。
Mark Storey-Smith

0

你不需要SUM,如果你并不需要找回它的两倍; 如果您只对id具有的感兴趣,SUM(hours) > 50则以下内容完全有效:

SELECT id,
FROM mytable
GROUP BY id
HAVING sum(hours) > 50;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.