Anche se ho lavorato con molti DBMS diversi, mostrerò solo il risultato di provarlo su SQL Server. Considera questa query, che include persino un CAST nell'espressione. Esaminando il piano di query, l'espressione sum(cast(number as bigint))
viene eseguita solo una volta, che è definita come DEFINE:([Expr1005]=SUM([Expr1006]))
.
set showplan_text on
select type, sum(cast(number as bigint))
from master..spt_values
group by type
having sum(cast(number as bigint)) > 100000
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|--Filter(WHERE:([Expr1005]>(100000)))
|--Hash Match(Aggregate, HASH:([Expr1004]), RESIDUAL:([Expr1004] = [Expr1004]) DEFINE:([Expr1005]=SUM([Expr1006])))
|--Compute Scalar(DEFINE:([Expr1004]=CONVERT(nchar(3),[mssqlsystemresource].[sys].[spt_values].[type],0), [Expr1006]=CONVERT(bigint,[mssqlsystemresource].[sys].[spt_values].[number],0)))
|--Index Scan(OBJECT:([mssqlsystemresource].[sys].[spt_values].[ix2_spt_values_nu_nc]))
Esso non può essere molto evidente in precedenza, dal momento che non mostra il risultato SELECT, quindi ho aggiunto un *10
alla query di seguito. Si noti che ora include un passaggio aggiuntivo DEFINE:([Expr1006]=[Expr1005]*(10))
(passaggi eseguiti dal basso verso l'alto) che dimostra che la nuova espressione lo richiedeva per eseguire un calcolo aggiuntivo. Tuttavia, anche questo è ottimizzato, in quanto non ricalcola l'intera espressione - semplicemente, sta prendendo Expr1005 e moltiplicandolo per 10!
set showplan_text on
select type, sum(cast(number as bigint))*10
from master..spt_values
group by type
having sum(cast(number as bigint)) > 100000
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|--Compute Scalar(DEFINE:([Expr1006]=[Expr1005]*(10)))
|--Filter(WHERE:([Expr1005]>(100000)))
|--Hash Match(Aggregate, HASH:([Expr1004]), RESIDUAL:([Expr1004] = [Expr1004]) DEFINE:([Expr1005]=SUM([Expr1007])))
|--Compute Scalar(DEFINE:([Expr1004]=CONVERT(nchar(3),[mssqlsystemresource].[sys].[spt_values].[type],0), [Expr1007]=CONVERT(bigint,[mssqlsystemresource].[sys].[spt_values].[number],0)))
|--Index Scan(OBJECT:([mssqlsystemresource].[sys].[spt_values].[ix2_spt_values_nu_nc]))
questo è molto probabile che come tutti gli altri DBMS funzionano così, almeno considerando le principali quelli cioè PostgreSQL, Sybase, Oracle, DB2, Firebird, MySQL.