¿Está usando SUM () dos veces subóptimo?


8

Sé que tengo que escribir SUMdos veces, si deseo usarlo en una HAVINGcláusula (o usar una tabla derivada de lo contrario):

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

Mi pregunta ahora es si esto es subóptimo o no. Como programador, esta consulta parece que el DB calculará la suma dos veces. ¿Es así o debo confiar en las optimizaciones que el motor DB hará por mí?

Actualización: una explicación de una consulta comparable:

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)

¿Puedes publicar la explicación?
Ste

No voy a responder a esto ya que hay una buena explicación concisa aquí : "En caso de que se esté preguntando por qué no se puede hacer referencia a los alias SELECT más adelante en la consulta, al igual que en la cláusula WHERE, que todo tiene que ver con el orden de evaluación. SQL no se evalúa en el orden en que está escrito. La lista SELECT se evalúa casi en último lugar, y su contenido aún no existe efectivamente cuando se procesan HAVING, etc. Esto se vuelve importante cuando la lista select incluye funciones con efectos [...] secundarios "
dezso

... esta es la razón por la que no puede hacer referencia a la columna agregada en la HAVINGcláusula, pero, a mi entender, internamente esto se hace al revés.
dezso

2
@BartFriederichs bueno, muchas personas se quejan junto a estas líneas (me quejé también hasta que no me acostumbré ...) No se ejecuta dos veces y probablemente podría hacerse usando un alias HAVING(y luego sacando la definición de columna de la SELECTcláusula) - por alguna razón simplemente no hacen eso.
dezso

3
Creo que dejar que el motor DB se preocupe por las optimizaciones debería ser una segunda naturaleza para un profesional de RDBMS. SQL es un 4GL, por lo que estamos definiendo el conjunto de resultados que queremos, no el medio por el cual se logra. Hay muchos otros problemas por los que no nos preocupamos en su mayor parte: el orden de unión o la transformación de EXISTS en una unión, por ejemplo. Este problema en particular es más un problema desde la perspectiva "No te repitas" para expresiones complejas, pero las soluciones razonables (vistas en línea, CTE) pueden ayudar con eso.
David Aldridge

Respuestas:


3

La suma solo se calcula una vez.

Verifiqué esto 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;

y luego usó un depurador para verificar cuántas veces int4_sum(la función de transición detrás del sumagregado) se llamó: una vez.


0

Compara tu consulta

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

Para este equivalente, un cheque en lo que difieren

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

1
Puedo ver a qué te refieres, pero en su forma actual, esto no es una "buena" respuesta. Publique la explicación para cada uno con un poco más de comentarios y será bueno para algunos votos positivos.
Mark Storey-Smith

0

No tiene que escribir SUMdos veces si no necesita recuperarlo; si solo está interesado en que ids tenga un mensaje, SUM(hours) > 50entonces lo siguiente es perfectamente válido:

SELECT id,
FROM mytable
GROUP BY id
HAVING sum(hours) > 50;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.