私はさまざまな DBMS を扱ってきましたが、SQL Server でこれを証明した結果のみを示します。式に CAST が含まれている次のクエリを考えてみましょう。クエリ プランを見ると、式sum(cast(number as bigint))
は として定義されている 1 回だけ取得され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]))
上記では SELECT の結果が表示されないため、わかりにくいかもしれません。そのため*10
、以下のクエリに a を追加しました。追加のステップが 1 つ含まれていることに注意してくださいDEFINE:([Expr1006]=[Expr1005]*(10))
(ステップは下から上に実行されます)。これは、新しい式が追加の計算を実行する必要があることを示しています。それでも、式全体を再計算するわけではないので、これでも最適化されています。単に、Expr1005 を取得して 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]))
これは、少なくとも PostgreSQL、Sybase、Oracle、DB2、Firebird、MySQL などの主要な DBMS を考慮すると、他のすべての DBMS も同様に機能する可能性が非常に高いです。