是否有关于SQL实现的标准,可以在同一查询中多次调用同一聚合函数?
例如,基于流行的示例架构,考虑以下示例:
SELECT Customer,SUM(OrderPrice) FROM Orders GROUP BY Customer HAVING SUM(OrderPrice)>1000
大概需要花费计算时间才能计算出SUM(OrderPrice)的值。每次对聚合函数的引用都会产生此成本,还是为特定查询存储结果?
或者,在这种情况下,没有针对SQL引擎实现的标准吗?
尽管我使用过许多不同的DBMS,但我只会向您展示在SQL Server上证明这一结果。考虑一下该查询,该查询甚至在表达式中包含一个CAST。从查询计划来看,该表达式sum(cast(number as bigint))仅采用一次,定义为DEFINE:([Expr1005]=SUM([Expr1006]))。
sum(cast(number as bigint))
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在下面的查询中添加了一个。请注意,它现在包括一个额外的步骤DEFINE:([Expr1006]=[Expr1005]*(10))(步骤从下至上),这表明新表达式需要它执行额外的计算。但是,即使这是经过优化的,因为它不会重新计算整个表达式- 只是,它使用的是Expr1005并将其乘以10!
*10
DEFINE:([Expr1006]=[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也是如何工作的,这很有可能。