2012-10-13 48 views
5

對於在同一查詢中對同一聚合函數進行多次調用的SQL實現有沒有標準?是否有SQL集合函數計算的標準?

例如,考慮下面的例子中,基於一個流行的示例性模式:

SELECT Customer,SUM(OrderPrice) FROM Orders 
GROUP BY Customer 
HAVING SUM(OrderPrice)>1000 

據推測,需要花費計算時間,以計算SUM(OrderPrice)的值。這是爲了引用聚合函數的每個引用而產生的成本,還是針對特定查詢存儲的結果?

或者,對於這種情況,SQL引擎執行沒有標準嗎?

回答

3

儘管我已經使用了許多不同的DBMS,但我只會向您顯示在SQL Server上證明這一點的結果。考慮這個查詢,它甚至在表達式中包含一個CAST。查看查詢計劃,表達式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])) 

它可能不是很明顯上面,因爲它不顯示選擇的結果,所以我添加了一個*10下面的查詢。注意它現在包含一個額外的步驟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])) 

這很可能是所有其他DBMS是如何工作的,以及,至少考慮到主要的PostgreSQL的即時,Sybase,甲骨文,DB2,火鳥,MySQL的。

相關問題