2010-03-02 55 views
2

取一個簡單的OrderDetail表,每個記錄有一個QuantityUnitPrice。要獲得每個訂單與SQL的總價值是簡單XQuery分組和聚合函數總是很慢嗎?

SELECT OrderID, SUM(UnitPrice*Quantity) 
FROM OrderDetail 
GROUP BY OrderID 

錶轉換爲XML文件後,使用XQuery我能夠得到這樣

for $orderId in distinct-values(doc('orderDetails.xml')//orderDetails/OrderID) 
    let $totalValue := 
     sum(
     for $detail in doc("orderdetails.xml")//OrderDetails[OrderID =$orderId] 
     return $detail/Quantity * $detail/UnitPrice 
    ) 
return <order id="{$orderId}" totalValue="{$totalValue}" /> 

忽略相同的信息純粹的愚蠢獲取這樣的信息,有沒有更好的方式來編寫XQUERY表達式?因爲它非常非常慢(我正在使用XMLSpy)。

回答

2

這是。1.0的一大缺陷,併爲此一組-BY子句中XQuery 1.1增加了,他們已經通過條款增加了一個組,所以您的查詢應該是這樣的:

for $orderDetails in doc('orderDetails.xml')//OrderDetails) 
let $orderId = $orderDetails/OrderID 
let $orderCost = $orderDetails/Quantity * $orderDetails/UnitPrice 
group by $orderId 
let $totalValue := sum($orderCost) 
return <order id="{$orderId}" totalValue="{$totalValue}" /> 

不幸的是,XQuery 1.1仍然只是一個工作草案,很少有實現可用。

我們的實現(XQSharp)試圖發現您使用的模式並更高效地執行組(這在查詢計劃中顯示爲分組)。不幸的是,我們的實現並沒有在你的特定情況下發現一個組。

第一個問題是套管差異(「orderdetails.xml」vs「orderDetails.xml」,//orderDetails vs //OrderDetails) - 我會認爲這些只是拼寫錯誤。

最大的問題是,你寫的不是一個微不足道的小組!

除非您使用的模式表明否則,靜態分析無法確定每個節點只有一個OrderID,並且OrderID的原子化值可能有多個項目(如果它有一個列表作爲其模式類型)。這意味着distinct-values(doc('orderDetails.xml')//orderDetails/OrderID)的靜態分析不能確定每個節點只有一個密鑰。

爲了解決這個查詢可以寫成如下:

for $orderId in distinct-values(doc("orderDetails.xml")/OrderDetails/exactly-one(OrderID/data(.))) 
let $totalValue := 
    sum(
     for $detail in doc("orderDetails.xml")/OrderDetails[exactly-one(OrderID/data(.)) = $orderId] 
     return $detail/Quantity * $detail/UnitPrice 
    ) 
return <order id="{$orderId}" totalValue="{$totalValue}" /> 

此查詢,則具有相同的語義爲一組,通過,並應當在這樣的優化。正如它發生的那樣,這仍然不能通過XQSharp優化到一個組,所以我已經將它作爲一個針對我們的軟件的錯誤提交。無論XmlSpy是否執行此優化,我都不能說。