Это серьезный недостаток в 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
против //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 эту оптимизацию или нет.