linq查询与where子句中的聚合

时间:2012-07-12 07:36:29

标签: .net linq aggregate

我有一个包含开始/结束日期的对象列表。我试图找到当前记录,如果当前记录存在,或者失败,最近过期的记录。

  • 当前定义为过去的非空开始日期,以及将来的空结束日期(开放结束)或结束日期。
  • 最近过期可定义为没有最长结束日期的当前时间段。从理论上讲,每个对象表示的时间跨度不应该重叠,因此我希望最大结束日期足以满足最近过期的时间。

我试图关注this answer类似的问题,但是如果列表中有其他条目未来的日期(即有开始/结束日期),我似乎无法找到正确的条目两者都在未来)。

我的尝试如下:a是开始日期,b是结束日期,c是我在调试时使用的指示符,d用于定义列表条目类型。我只对2型感兴趣。

   [TestMethod]
    public void TestRetrievalOfListElements()
    {

        var baseDate = DateTime.Now;

        var list = new[]
        {
             new { a = new DateTime?(baseDate.AddDays(-90)), 
                   b = new DateTime?(baseDate.AddDays(-60)), c = "LongExpired", d=1 },
             new { a = new DateTime?(baseDate.AddDays(-190)), 
                   b = new DateTime?(baseDate.AddDays(-160)), c = "LongestExpired", d=1 },
             new { a = new DateTime?(baseDate.AddDays(-59)), 
                   b = new DateTime?(baseDate.AddDays(+20)), c = "Current", d=1 },
             new { a = new DateTime?(baseDate.AddDays(-159)), 
                   b = new DateTime?(baseDate.AddDays(-91)), c = "LongerExpired", d=1 },
             new { a = new DateTime?(baseDate.AddDays(-90)), 
                   b = new DateTime?(baseDate.AddDays(-60)), c = "LongExpired", d=2 },
             new { a = new DateTime?(baseDate.AddDays(-190)), 
                   b = new DateTime?(baseDate.AddDays(-160)), c = "LongestExpired", d=2 },
             new { a = new DateTime?(baseDate.AddDays(-59)), 
                   b = new DateTime?(baseDate.AddDays(+20)), c = "Current", d=2 },
             new { a = new DateTime?(baseDate.AddDays(-159)), 
                   b = new DateTime?(baseDate.AddDays(-91)), c = "LongerExpired", d=2 },
             new { a = new DateTime?(baseDate.AddDays(+21)), 
                   b = new DateTime?(baseDate.AddDays(+60)), c = "Future", d=2 },

        }.ToList();

        // The following isn't really right either as it doesn't take into account
        // whether d is of type 1 or 2 either. Not sure how to combine aggregates and
        // other conditions ie MIN and of type 2

        var oldestEntry = (from x in list
                          where x.a == list.Min(d => d.a) &&
                          x.d == 2
                          select x).FirstOrDefault();

        Assert.IsTrue(oldestEntry.a == baseDate.AddDays(-190), "Expected oldest date to be 190 days earlier than today");

        var latestEntryThatIsntInTheFuture = 
                          (from x in list
                          from y in list.Where(z => z.d == 2 && z.a <= baseDate)
                          where x.a == list.Max(d => d.a) &&
                          x.d == 2
                          select x).FirstOrDefault();

        Assert.IsTrue(latestEntryThatIsntInTheFuture.a == baseDate.AddDays(-59), "Expected latest date that isn't in the future to be 59 days earlier than today");



    }

1 个答案:

答案 0 :(得分:1)

这可能就是你要找的东西:

// Find the current which is defined as a non null start date that is in the past 
// and either a null end date (open ended) or and end date in the future. 
var now = DateTime.Now;
var current = list
    .Where(x => x.a.HasValue && x.a.Value < now && (!x.b.HasValue || x.b.Value > now))
    .FirstOrDefault();
if (current == null)
{ 
    //Then find most recently expired 
    current = list.Where(x => x.b.HasValue)
                  .OrderByDescending(x => x.b)
                  .FirstOrDefault();
}

因此,我认为您不需要在查询中使用聚合。