L'uso di SUM () è due volte non ottimale?


8

So che devo scrivere SUMdue volte, se desidero usarlo in una HAVINGclausola (o utilizzare una tabella derivata altrimenti):

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

La mia domanda ora è, se questo non è ottimale. Come programmatore, questa query sembra che il DB calcolerà la somma due volte. È così o dovrei fare affidamento sulle ottimizzazioni che il motore DB farà per me?

Aggiornamento: una spiegazione di una query comparabile:

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)

puoi pubblicare la spiegazione?
Ste

Non voglio rispondere a questa in quanto v'è una bella, concisa spiegazione qui : "Nel caso in cui vi state chiedendo il motivo per cui non si può fare riferimento ai alias selezionare In seguito nella query, come nella clausola WHERE, è tutto a che fare con l'ordine di valutazione. SQL non viene valutato nell'ordine in cui è scritto. L'elenco SELECT viene effettivamente valutato quasi per ultimo e il suo contenuto effettivamente non esiste ancora quando HAVING ecc. vengono elaborati. Ciò diventa importante quando l'elenco select include funzioni con effetti collaterali [...] "
dezso

... questo è il motivo per cui non puoi semplicemente fare riferimento alla colonna aggregata nella HAVINGclausola - ma, per quanto ne sappia, internamente questo è piuttosto fatto al contrario.
dezso,

2
@BartFriederichs bene, molte persone si lamentano a fianco di queste righe (mi sono lamentato anche fino a quando non mi ci sono abituato ...) Non viene eseguito due volte e probabilmente potrebbe essere fatto usando un alias in HAVING(e quindi tirando la definizione della colonna dalla SELECTclausola) - per qualche motivo non lo fanno.
dezso,

3
Penso che lasciare che il motore DB si preoccupi delle ottimizzazioni dovrebbe essere una seconda natura per un professionista RDBMS. SQL è un 4GL, quindi stiamo definendo il set di risultati che desideriamo, non i mezzi con cui viene raggiunto. Ci sono molti altri problemi là fuori di cui non ci preoccupiamo per la maggior parte - ad esempio l'ordine dei join o la trasformazione di EXISTS in un join. Questo particolare problema è più un problema dal punto di vista "Non ripetere te stesso" per un'espressione complessa, ma soluzioni alternative sensate (viste in linea, CTE) possono essere di aiuto.
David Aldridge,

Risposte:


3

La somma viene calcolata una sola volta.

Ho verificato usando

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;

e quindi ha utilizzato un debugger per verificare quante volte int4_sum(la funzione di transizione dietro l' sumaggregato) è stata chiamata: una volta.


0

Confronta la tua query

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

A questo equivalente si controlla in cosa differiscono

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

1
Vedo cosa stai ottenendo, ma nella sua forma attuale questo non costituisce una risposta "buona". Pubblica la spiegazione per ciascuno con un po 'più di commenti e sei bravo per alcuni voti.
Mark Storey-Smith,

0

Non è necessario scrivere SUMdue volte se non è necessario recuperarlo; se ti interessa solo idavere una s, SUM(hours) > 50allora è perfettamente valido quanto segue:

SELECT id,
FROM mytable
GROUP BY id
HAVING sum(hours) > 50;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.