2014-03-06 72 views
2

我正在尝试使用Altova XMLSpy和XQuery 1.0为每个客户返回最近的订单。XQuery每个客户的最近订单

在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> 

道歉的XML已经从MS Access导出的可怕的标签名称。

请帮忙!提前致谢。

<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> 
+1

请始终给出示例数据来处理。由于对数据的误解,其他一切都会导致一系列后续问题。 –

+2

你在用什么具体的数据库?他们都说“SQL”作为他们的查询语言 - 但像XML支持这样的东西在供应商和供应商之间差别很大。因此,请使用您正在使用的具体数据库更新您的代码 - 无论是MySQL,Postgres,Sybase,IBM DB2,Oracle,SQL Server,Interbase,还是您正在使用的任何其他应用程序! –

+1

对于我使用MS Access的SQL,但XQuery没有使用数据库,查询是从独立XML文档(现在我已经提供了一个片段)在Altova XMLSpy中运行 – dinkydani

回答

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> 
+0

除了原始的SQL查询返回'订单ID','客户ID','员工ID','订单日期',而这只返回日期。 –

+0

谢谢,我错过了;我已更新我的示例。 – joemfb

+0

唉,但它会返回每个客户的所有订单(将用数据更新我的问题)。我只需要每个客户的最近订单,这是我遇到麻烦的原因:( – dinkydani

1

XQuery 3.0解决方案。

一个高阶函数类似撒克逊:最高()都可以在这里有用:看

http://www.saxonica.com/documentation/#!functions/saxon/highest

有了这样的功能,代码变成类似如下(我假设“样本数据中的订单”元素代表了一个订单,并重复):

for $o in //Orders 
group by $o/Customer_ID 
return saxon:highest($o, function($order){xs:date($order/Order_Date)}) 

如果你不使用撒克逊你可以写撒克逊:最高()函数自己,像这样:

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 
} 
相关问题