2012-12-19 44 views
4

我有以下結構的XML文件: 可以在SQL做排名超過分區,如何在LINQ做XML

<Entities> 
    <Request> 
     <ID> A1 </ID> <!-- Can be multiple records with same values --> 
     <Finance> 
      <StartDate> Some Date </StartDate> <!-- Unique per ID --> 
     </Finance> 
    <Request> 
    <Request> ... </Request> 
</Entities> 

有可與同一ID,但在多個請求在這種情況下,StartDate需要根據請求而不同。

我需要爲每個ID取出最新的兩個日期。

如果這是通過ID和起始日期列的SQL表,我會使用下面的查詢這是工作的罰款:

SELECT ID, StartDate 
FROM (SELECT ID, StartDate, RANK() 
      OVER (PARTITION BY ID ORDER BY StartDate DESC) rank 
     FROM Request) 
WHERE rank IN ('1','2') 

但是我對XML格式的數據,最好的我能想出根據ID,StartDate訂購數據。我仍然需要挖掘每個ID的最新兩個日期。

變種cafrequests =

from request in xdoc.Descendants("Request") 
orderby (int)request.Element("ID"), 
(DateTime)request.Element("Finance").Element("StartDate") ascending 
select new 
{ 
    ID = request.Element("ID"), 
    StartDate = request.Element("Finance").Element("StartDate"), 
}; 

使用採取(2)將只取箱頂部2行數據的,而不是頂部2%ID。

那麼,任何人都可以告訴我什麼是LINQ中上述SQL語句的等價物?我不想在C#中使用循環和條件語言來解析和管理XML,而且我對LINQ還很陌生(昨天已經閱讀並開始使用它),而且我還在閱讀文檔。

回答

2

這工作,我測試了它:

 XDocument doc = XDocument.Load(@"Data.xml"); 

     var result2 = doc.Element("Entities") 
      .Elements("Request") 
      .GroupBy(key => key.Element("ID").Value, el => DateTime.Parse(el.Element("Finance").Element("StartDate").Value)) 
      .Select(el => 
       new 
       { 
        id = el.Key, 
        max2 = el.OrderByDescending(date => date).Take(2) 
       }); 
  • doc.Element("Entities") - 獲得命名的實體元素,這就是文檔的根元素,檢索該元素的另一種方法是doc.Root
  • Elements("Request") - 變名爲Request的元素是實體的子項
  • GroupBy - 是一種有點類似於SQL中的GROUP BY的方法,第一個參數是要運行的元素用於分組,它是一個Request元素的子元素,第二個參數是元素選擇器函數,用於從StartDate元素(它是子元素的子元素,它是Request元素的子元素)解析DateTime
  • .Select(el => new...) - 方法創建,其保存有ID最高日期

這裏是一個查詢,得到了相同的結果,但寫在查詢語法ID和2記錄匿名類型(例如以上方法的語法):

 var result = from el in doc.Root.Elements("Request") 
        group DateTime.Parse(el.Element("Finance").Element("StartDate").Value) by el.Element("ID").Value into grouped 
        select new { 
         id = grouped.Key, 
         max2 = (from el in grouped 
           orderby el descending 
           select el) 
           .Take(2) 
        }; 
+0

雖然我不瞭解整個代碼,但它確實有效。謝謝:) –

+1

不客氣,我很樂意提供幫助。我添加了一些解釋和用查詢語法編寫的例子,也許它澄清了查詢中發生了什麼:) –

1

我們不能按ID分組並挑選最近的日期嗎?像這樣的東西。如果您正在獲取結果集中的ID列表和相應的日期(cafrequests)

var result = cafrequests.GroupBy(x=>x.Id).Select(x=>new{ x.Key,Dates = x.OrderByDescending(y => y.StartDate).Select(y=>y.StartDate).Take(2)}).ToDictionary(x=>x.Key); 

這會爲您提供每個ID的前2個日期。