SUM()を2回使用するのは最適ではありませんか?


8

句で使用する場合(または派生テーブルを使用する場合)SUM、2回記述する必要があることはわかっていHAVINGます。

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

私の質問は、これが最適ではないかどうかです。プログラマーとして、このクエリは、DBが合計を2回計算するように見えます。そうですか、それともDBエンジンが行う最適化に依存すべきですか?

更新:比較可能なクエリの説明:

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)

説明を投稿できますか?
2013年

ここには素敵で簡潔な説明があるので、これには答えません。「WHERE句のように、クエリの後半でSELECTエイリアスを参照できない理由がわからない場合は、すべて順序で行う必要があります。 SQLは記述された順序で評価されません。SELECTリストは実際にはほぼ最後に評価され、HAVINGなどが処理されるとき、その内容は実際にはまだ存在しません。これは、select-listに副作用[...] "
dezso 2013年

...これが、HAVING句で集計列を単に参照できない理由ですが、私の理解では、これはむしろ逆に行われます。
dezso 2013年

2
@BartFriederichsよく、多くの人々がこれらの行に沿って不平を言います(私はそれに慣れないまで私も不平を言いました...)これは2回実行されず、おそらくエイリアスを使用してHAVING(そして次に列定義をプルすることによって)できますSELECT節から)-何らかの理由で彼らはそれをしません。
dezso 2013年

3
DBエンジンに最適化を心配させることは、RDBMSの実践者にとって第二の性質であるべきだと思います。SQLは4GLなので、目的の結果セットを定義するのであって、それを実現する手段を定義するのではありません。他にも多くの問題があります。たとえば、結合順序や、EXISTSから結合への変換などです。この特定の問題は、複雑な表現の「自分を繰り返さないでください」という観点からはもっと問題ですが、賢明な回避策(インラインビュー、CTE)はそれらを助けることができます。
David Aldridge 2013年

回答:


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_sumsumアグリゲートの背後にある遷移関数)が呼び出されたかを確認しました。


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;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.