为每条记录选择一个OrderDetail
和Quantity
的简单UnitPrice
表。要使用SQL获取每个Order的总值,它就像
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)。
答案 0 :(得分:2)
这是XQuery 1.0中的一个主要缺陷,因此在XQuery 1.1中添加了一个group-by子句,它们添加了一个group by子句,因此您的查询将如下所示:
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”与“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}" />
此查询具有与group-by相同的语义,因此应进行优化。碰巧这仍然没有在XQSharp中对组进行优化,因此我将此作为对我们软件的错误提交。无论XmlSpy是否执行此优化,我都不能说。