O uso de SUM () é duas vezes abaixo do ideal?

8

Eu sei que tenho que escrever SUMduas vezes, se desejar usá-lo em uma HAVINGcláusula (ou usar uma tabela derivada de outra forma):

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

Minha pergunta agora é se isso é ou não ideal. Como programador, essa consulta parece que o banco de dados calculará a soma duas vezes. É assim ou devo confiar nas otimizações que o mecanismo de banco de dados fará por mim?

Atualização: uma explicação de uma consulta comparável:

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
fonte
você pode postar a explicação?
Ste
Não vou responder isso, pois há uma explicação concisa e agradável aqui : "Caso você esteja se perguntando por que não pode se referir aos aliases SELECT posteriormente na consulta, como na cláusula WHERE, tudo tem a ver com ordem O SQL não é avaliado na ordem em que está escrito. A lista SELECT é realmente avaliada por último e seu conteúdo ainda não existe efetivamente quando HAVING etc são processados. Isso se torna importante quando a lista de seleção inclui funções com efeitos colaterais "[...]"
dezso 28/05
... é por isso que você não pode apenas fazer referência à coluna agregada na HAVINGcláusula - mas, no meu entendimento, internamente isso é feito de outra maneira.
Dez28
2
@BartFriederichs bem, muitas pessoas reclamam ao longo destas linhas (eu também reclamei até não me acostumar com isso ...) Ele não é executado duas vezes e provavelmente poderia ser feito usando um alias em HAVING(e depois puxando a definição da coluna da SELECTcláusula) - por alguma razão, eles simplesmente não fazem isso.
Dez28
3
Penso que deixar o mecanismo de banco de dados se preocupar com otimizações deve ser uma segunda natureza para um profissional de RDBMS. Como o SQL é um 4GL, estamos definindo o conjunto de resultados que queremos, não os meios pelos quais ele é alcançado. Existem muitos outros problemas por aí nos quais não nos preocupamos na maior parte - ordem de junção ou transformação de EXISTS em uma junção, por exemplo. Esse problema específico é mais um problema da perspectiva "Não se repita" para expressões complexas, mas soluções alternativas sensatas (visualizações em linha, CTEs) podem ajudar com isso.
David Aldridge 28/05

Respostas:

3

A soma é calculada apenas uma vez.

Eu verifiquei isso 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, em seguida, usou um depurador para verificar quantas vezes int4_sum(a função de transição atrás do sumagregado) foi chamada: uma vez.

Peter Eisentraut
fonte
0

Compare sua consulta

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

Para este equivalente, verifique o que diferem

explain
select *
from (
    select sum(counttodo) counttodo
    from orderline
    group by orderlineid
) s
where counttodo > 100
Clodoaldo
fonte
11
Eu posso ver no que você está falando, mas, na sua forma atual, isso não contribui para uma resposta "boa". Poste a explicação de cada um com um pouco mais de comentários e você estará pronto para alguns votos positivos.
Mark-Storey-Smith
0

Você não precisa escrever SUMduas vezes se não precisar recuperá-lo; se você estiver interessado apenas em idter um SUM(hours) > 50, o seguinte é perfeitamente válido:

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