2012-07-12 6 views
0

시작/종료 날짜가 포함 된 개체 목록이 있습니다. 현재 레코드가 존재하는 경우 현재 레코드를 찾거나 가장 최근에 만료 된 레코드를 찾지 못했습니다.where 절의 집계가있는 linq 쿼리

  • 현재는 null이 아닌 시작 날짜로 정의되며 향후 null 종료 날짜 (종료시) 또는 종료 날짜 중 하나입니다.
  • 가장 최근에 만료 된 것은 최대 종료 날짜가없는 현재 기간이없는 것으로 정의 할 수 있습니다. 이론 상으로는 각 객체에 의해 표시되는 시간 범위가 중복되어서는 안되기 때문에 최대 종료 날짜가 최근에 만료되기에 충분할 것으로 기대합니다.

나는 비슷한 질문에 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

유형에만 관심이 :

// 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(); 
} 

그래서 당신은 내 의견으로는 쿼리에 집계가 필요하지 않습니다.

+0

언뜻보기에 이것은 꽤 좋아 보입니다. 쿼리에서 집계가 필요하지 않을 수도 있습니다. 주문을 단순히 적용하는 아이디어는 매우 깔끔합니다. 나는 겉으로보기에는 쉬운 표정을 아주 어렵게 만드는 초자연적 인 기술을 가지고 있다고 생각합니다. 코드에 대해 몇 가지 테스트를 수행하고 어떻게 진행되는지 살펴 보겠습니다. 감사. –

+0

그것은 대우를 작동합니다. 감사. –