4

我有一个具有以下结构的 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 和 StartDate 列的 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 挖出最近的两个日期。

var 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"),
};

使用 Take(2) 只会获取前 2 行数据,而不是每个 ID 的前 2 行。

那么任何人都可以告诉我 LINQ 中上述 SQL 语句的等价物是什么吗?我不想在 C# 中使用循环和条件来解析和管理 XML,而且我对 LINQ 还是很陌生(昨天阅读并开始使用它),我仍在阅读文档。

4

2 回答 2

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")- 获取名为 Entity 的元素,它是文档的根元素,另一种检索此元素的方法是doc.Root
  • Elements("Request")- 获取名为 Request 的元素,它们是 Entity 的子元素
  • GroupBy- 是一种类似于GROUP BYSQL 的方法,第一个参数是要用于分组的元素,它是 Request 元素的子元素,第二个参数是DateTime从 StartDate 元素(它是财务元素,它是请求元素的子元素)
  • .Select(el => new...)- 创建匿名类型的方法,该类型包含 ID 和 2 个具有最高 ID 日期的记录

这是一个得到相同结果的查询,但是用查询语法编写(上面的示例是方法语法):

        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)
                     };
于 2012-12-19T08:19:57.950 回答
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 个日期。

于 2012-12-19T08:05:36.217 回答