我正在尝试使用Altova XMLSpy和XQuery 1.0来返回每个客户的最新订单。
在SQL中,查询是这样的:
SELECT `Order ID`, `Customer ID`, `Employee ID`, `Order Date`
FROM Orders AS O1
WHERE `Order Date` =
(SELECT MAX(`Order Date`)
FROM Orders AS O2
WHERE O2.[Customer ID] = O1.[Customer ID]);
返回16行但我无法在XQuery中使用任何类似的东西。
我尝试了多种代码变体,我认为最接近的是:
<result>
{
for $cust in distinct-values(doc("Orders.xml")//Orders/Customer_x0020_ID)
return
<Customer>
{
for $order in doc("Orders.xml")//Orders
where $cust = $order/Customer_x0020_ID
return max(xs:string($order/Order_x0020_Date))
}
</Customer>
}
</result>
为从MS Access导出XML的可怕标记名称道歉。
请帮忙!提前谢谢。
<Orders>
<Order_x0020_ID>30</Order_x0020_ID>
<Employee_x0020_ID>9</Employee_x0020_ID>
<Customer_x0020_ID>27</Customer_x0020_ID>
<Order_x0020_Date>2006-01-15T00:00:00</Order_x0020_Date>
</Orders>
修改 在尝试joemfb的解决方案后,当我只需要最近(或最长日期)时,我会收到每个客户的所有订单:
<Customer>
<Order_x0020_ID>57</Order_x0020_ID>
<Customer_x0020_ID>27</Customer_x0020_ID>
<Employee_x0020_ID>9</Employee_x0020_ID>
<Order_x0020_Date>2006-04-22T00:00:00</Order_x0020_Date>
<Order_x0020_ID>30</Order_x0020_ID>
<Customer_x0020_ID>27</Customer_x0020_ID>
<Employee_x0020_ID>9</Employee_x0020_ID>
<Order_x0020_Date>2006-01-15T00:00:00</Order_x0020_Date>
</Customer>
<Customer>
<Order_x0020_ID>80</Order_x0020_ID>
<Customer_x0020_ID>4</Customer_x0020_ID>
<Employee_x0020_ID>2</Employee_x0020_ID>
<Order_x0020_Date>2006-04-25T17:03:55</Order_x0020_Date>
<Order_x0020_ID>58</Order_x0020_ID>
<Customer_x0020_ID>4</Customer_x0020_ID>
<Employee_x0020_ID>3</Employee_x0020_ID>
<Order_x0020_Date>2006-04-22T00:00:00</Order_x0020_Date>
<Order_x0020_ID>61</Order_x0020_ID>
<Customer_x0020_ID>4</Customer_x0020_ID>
<Employee_x0020_ID>9</Employee_x0020_ID>
<Order_x0020_Date>2006-04-07T00:00:00</Order_x0020_Date>
<Order_x0020_ID>34</Order_x0020_ID>
<Customer_x0020_ID>4</Customer_x0020_ID>
<Employee_x0020_ID>9</Employee_x0020_ID>
<Order_x0020_Date>2006-02-06T00:00:00</Order_x0020_Date>
<Order_x0020_ID>31</Order_x0020_ID>
<Customer_x0020_ID>4</Customer_x0020_ID>
<Employee_x0020_ID>3</Employee_x0020_ID>
<Order_x0020_Date>2006-01-20T00:00:00</Order_x0020_Date>
</Customer>
答案 0 :(得分:2)
更新:我修改了查询以返回最近订单的所有元素。此查询有点尴尬,因为源XML不按顺序对元素进行分组。
<result>
{
for $cust in distinct-values(doc("Orders.xml")//Orders/Customer_x0020_ID)
return
<Customer>
{
let $date :=
(
for $cid in doc("Orders.xml")//Orders/Customer_x0020_ID[. eq $cust]
let $date := $cid/following-sibling::Order_x0020_Date[1]
order by xs:dateTime($date) descending
return $date
)[1]
return
(
$date/preceding-sibling::Order_x0020_ID[1],
$date/preceding-sibling::Customer_x0020_ID[1],
$date/preceding-sibling::Employee_x0020_ID[1],
$date
)
}
</Customer>
}
</result>
答案 1 :(得分:1)
XQuery 3.0解决方案。
像saxon这样的高阶函数:highest()在这里很有用:见
http://www.saxonica.com/documentation/#!functions/saxon/highest
使用这样的函数,代码变成如下所示(我假设样本数据中的“Orders”元素代表一个订单,并且重复):
for $o in //Orders
group by $o/Customer_ID
return saxon:highest($o, function($order){xs:date($order/Order_Date)})
如果您没有使用Saxon,您可以自己编写saxon:highest()函数,如下所示:
declare function saxon:highest($s as item()*, $f as function(item()*) as xs:anyAtomicValue) as item()?{
if (count($s) lt 2)
then head($s)
else (
let $h := saxon:highest(tail($s), $f)
return if ($f(head($s)) gt $f($h))
then head($s)
else $h
}