Home Full Site
LINQ : 그룹별 최대 / 최소

LINQ에서 테이블이나 데이타셋의 그룹별 결과를 구한 후, 그룹별 최대갑 혹은 최소값을 가지는 레코드를 리턴하기 위해서는, 먼저 특정 키(컬럼)에 따라 Group by를 시킨 후 이 중간 데이타셋으로부터 다시 최대/최소를 구하게 된다. 아래 예제는 LINQ 쿼리를 사용하여 group by로 GroupID별 그룹화 된 결과를 g에 담아 둔 후, select 문에서 g.Min()을 사용하여 최소값을 찾는 방식을 보여준다. SELECT문에서는 new {}를 사용하여 Anonymous Type을 새로 생성하고 여기서 GroupID와 SalesPerson 컬럼을 생성하고 있다. GroupID와 Sales는 상대적으로 쉽게 구할 수 있지만, SalesPerson은 직접적인 컬럼값 할당이 되지 못하므로, 다시 레코드를 찾아 할당하고 있다.

예제

private void button1_Click(object sender, EventArgs e)
{
    DataClasses1DataContext db = new DataClasses1DataContext();

    // LINQ : GROUP BY - MIN
    var result = from t in db.SalesTables
                    group t by t.GroupID into g
                    select new {
                        GroupID = g.Key,
                        SalesPerson = g.First(g2 => g2.Sales == g.Min(g3 => g3.Sales)).SalesPerson,
                        Sales = g.Min(p => p.Sales)
                    };

    foreach (var r in result)
    {
        Debug.WriteLine(r.GroupID + "," + r.SalesPerson + "," + r.Sales);
    }
}




[입력 데이타]
Sample

[결과]
1,Li,800
2,Jane,400
3,Irina,600

LINQ 확장메서드를 사용한 솔루션

위의 LINQ 쿼리를 LINQ 확장 메서드를 써서 다시 표현할 수 있다. 아래 예제에서 처럼, GroupBy() 메서드의 결과를 직접 받아 다시 Select() 메서드로 넘기고 이곳에서 다시 익명 타입 (Anonymous Type)을 생성하게 된다.

예제

private void button2_Click(object sender, EventArgs e)
{
    DataClasses1DataContext db = new DataClasses1DataContext();

    // 확장메서드를 사용한 LINQ 표현
    var result = db.SalesTables.GroupBy(t => t.GroupID).Select(g => new
    {
        GroupID = g.Key,
        SalesPerson = g.First(g2 => g2.Sales == g.Min(g3 => g3.Sales)).SalesPerson,
        Sales = g.Min(p => p.Sales)
    });

    foreach (var r in result)
    {
        Debug.WriteLine(r.GroupID + "," + r.SalesPerson + "," + r.Sales);
    }
}




© csharpstudy.com