Apakah menggunakan SUM () dua kali suboptimal?

8

Saya tahu saya harus menulis SUMdua kali, jika saya ingin menggunakannya dalam HAVINGklausa (atau menggunakan tabel turunan):

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

Pertanyaan saya sekarang adalah, apakah ini suboptimal atau tidak. Sebagai seorang programmer, permintaan ini sepertinya DB akan menghitung jumlah dua kali. Begitukah, atau haruskah saya mengandalkan optimisasi yang akan dilakukan mesin DB untuk saya?

Pembaruan: penjelasan tentang kueri yang sebanding:

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)
Bart Friederichs
sumber
dapatkah Anda memposting penjelasannya?
Ste
Saya tidak akan menjawab ini karena ada penjelasan yang bagus dan singkat di sini : "Jika Anda bertanya-tanya mengapa Anda tidak dapat merujuk ke alias SELECT nanti dalam kueri, seperti dalam klausa WHERE, itu semua berkaitan dengan pesanan evaluasi. SQL tidak dievaluasi dalam urutan yang ditulisnya. SELECT-list sebenarnya dievaluasi hampir terakhir, dan isinya secara efektif belum ada ketika HAVING dll diproses. Ini menjadi penting ketika daftar-pilih menyertakan fungsi dengan efek samping [...] "
dezso
... ini sebabnya Anda tidak bisa hanya merujuk kolom agregat dalam HAVINGklausa - tetapi, menurut pemahaman saya, secara internal ini agak dilakukan sebaliknya.
dezso
2
@ BartFriederichs, banyak orang mengeluh di samping kalimat-kalimat ini (saya telah mengeluh juga sampai saya tidak terbiasa ...) Itu tidak dieksekusi dua kali dan mungkin dapat dilakukan dengan menggunakan alias di HAVING(dan kemudian menarik definisi kolom dari SELECTklausa) - untuk beberapa alasan mereka tidak melakukannya.
dezso
3
Saya berpikir bahwa membiarkan mesin DB khawatir tentang optimisasi harus menjadi kebiasaan kedua bagi seorang praktisi RDBMS. SQL adalah 4GL, jadi kita mendefinisikan set hasil yang kita inginkan, bukan cara yang digunakan untuk mencapai. Ada banyak masalah lain di luar sana yang sebagian besar tidak kami khawatirkan - gabung pesanan, atau transformasi EXISTS menjadi gabung misalnya. Masalah khusus ini lebih merupakan masalah dari perspektif "Jangan Ulangi Diri Sendiri" untuk ekspresi yang kompleks, tetapi solusi yang masuk akal (pandangan in-line, CTE) dapat membantu dengan itu.
David Aldridge

Jawaban:

3

Jumlahnya hanya dihitung sekali.

Saya memverifikasi ini menggunakan

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;

dan kemudian menggunakan debugger untuk memeriksa berapa kali int4_sum(fungsi transisi di belakang sumagregat) dipanggil: sekali.

Peter Eisentraut
sumber
0

Bandingkan kueri Anda

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

Untuk ini setara cek di apa perbedaannya

explain
select *
from (
    select sum(counttodo) counttodo
    from orderline
    group by orderlineid
) s
where counttodo > 100
Clodoaldo
sumber
1
Saya dapat melihat apa yang Anda maksudkan tetapi dalam bentuk saat ini ini tidak membuat jawaban yang "baik". Posting penjelasan untuk masing-masing dengan sedikit komentar dan Anda baik untuk beberapa upvotes.
Mark Storey-Smith
0

Anda tidak perlu menulis SUMdua kali jika Anda tidak perlu mengambilnya; jika Anda hanya tertarik pada yang idmemiliki SUM(hours) > 50maka yang berikut ini benar-benar valid:

SELECT id,
FROM mytable
GROUP BY id
HAVING sum(hours) > 50;
Colin 't Hart
sumber