2013-05-29 2 views
3

이렇게 목록이 있습니다. 기본적으로 가장 최근의 상태가 현재 상태를 나타내는 여러 항목에 대한 상태 기록입니다.각 그룹의 최상위 항목에서 항목 및 쿼리를 그룹화하는 Linq 쿼리

Record Id  State  Date 
===== ===  ========= ======= 
1  A  Waiting  Jan 01 
2  A  InProgress Jan 02 
3  A  Finished Jan 03 
4  B  Waiting  Jan 02 
5  C  Waiting  Jan 01 
6  C  InProgress Jan 02 
7  D  Waiting  Jan 01 
8  D  InProgress Jan 02 

내가 찾고있는 것은 각 항목에 대해 '현재'상태를 쿼리 할 수 ​​있습니다. 예를 들어 다음과 같이 말하고 싶습니다. "모든 ID가 'InProgress'이고 ID가 D이고 ID가 C이지만 ID가 A가 아닙니다 (최신 상태가 'Finished'이므로).

일부 그룹화 및 일부 주문 또는 Maxing을 수행해야한다는 것을 알고 있지만 완전히 정리할 수는 없습니다.

+2

지금까지 해보신 것은 무엇입니까? 그룹화 순서 및 최대 값을 통해 우리가 한 일을 보여주고 잘못 된 곳을 알려줄 수 있습니다. 솔루션을받은 것보다 배우는 것이 훨씬 낫습니다 ... – Chris

답변

9
myList.GroupBy(m => m.Id) 
.Select(g => g.OrderByDescending(x => x.Date).First()) 
.Where(<your filter>); 
1

이 (오른쪽 순서로 배열하고, 가정 기록) 객체에 LINQ 인 경우, 당신은 할 수 있습니다 :

var latestById = records.GroupBy(record => record.Id) 
         .ToDictionary(group => group.Key, group => group.Last()); 

이는 GROUPBY 때문에 그룹에서 guarantees that "요소는에 굴복되어있다 그들이 소스에 나타나는 순서. "

는 기록 순서에 대한 보증을 할 수없는 경우, 내가 할 것 :

var latestById = records.GroupBy(record => record.Id) 
         .Select(group => group.MaxBy(r => r.Date)) 
         .ToDictionary(record => record.Id); 

MaxBymoreLinq에서 온다. 이 SQL에 LINQ를한다면 그건 그렇고

은 내가 할 것 :

var latestById = records.GroupBy(record => record.Id) 
         .Select(group => group.OrderByDescending(r => r.Date).First()) 
         .AsEnumerable() 
         .ToDictionary(record => record.Id); 
+0

소스에 나타나는 순서가 날짜 순서인지 알 수 없습니까? 그들은 예제에 있지만 기록이 날짜 순서대로라고 말하지 않았습니다. Nitpicky하지만 벌레의 근원 인 그 종류의 ... – Chris

+0

@Chris : 그것은 그렇게 보입니다. 그러나 그것이 사실이 아니라면 나는 길을 제공했습니다. – Ani

+0

감사합니다. Ani. 나는 그게 훨씬 더 나은 대답이라고 생각합니다. :) – Chris

2

여기 당신이 원하는 것을 할 수있는 몇 가지 코드입니다. 각 ID의 최신 상태를 가져오고 완료된 레코드를 무시합니다. 내가 실행할 수있는 완전한 작업 예제를 제공했습니다 (그리고 실제 데이터를 위해 잘 작동하도록).

//the example data provided by the OP 
var data = new [] 
{ 
    new { Record = 1, Id = "A", State = "Waiting", Date = new DateTime(2013, 1, 1) }, 
    new { Record = 2, Id = "A", State = "InProgress", Date = new DateTime(2013, 1, 2) }, 
    new { Record = 3, Id = "A", State = "Finished", Date = new DateTime(2013, 1, 3) },   
    new { Record = 4, Id = "B", State = "Waiting", Date = new DateTime(2013, 1, 1) },   
    new { Record = 5, Id = "C", State = "Waiting", Date = new DateTime(2013, 1, 1) }, 
    new { Record = 6, Id = "C", State = "InProgress", Date = new DateTime(2013, 1, 2) },   
    new { Record = 7, Id = "D", State = "Waiting", Date = new DateTime(2013, 1, 1) }, 
    new { Record = 8, Id = "D", State = "InProgress", Date = new DateTime(2013, 1, 2) }, 
}; 

var query = from d in data 
      //put the newest record first 
      orderby d.Date descending 
      //group by the id 
      group d by d.Id into groupedById 
      //get the latest record for each id 
      let latest = groupedById.First() 
      //filter out finished records 
      where latest.State != "Finished" 
      select latest; 

다음은 LinqPad의 출력입니다.

enter image description here

당신은 우리가 떨어져이 완료되기 때문에 무시되었습니다 "A"에서, 각 항목에 대한 최신 상태를 가지고 있음을 알 수 있습니다.

관련 문제