여러 열로 그룹화


967

LINQ에서 GroupBy 여러 열을 수행하는 방법

SQL에서 이와 비슷한 것 :

SELECT * FROM <TableName> GROUP BY <Column1>,<Column2>

이것을 LINQ로 변환하는 방법 :

QuantityBreakdown
(
    MaterialID int,
    ProductID int,
    Quantity float
)

INSERT INTO @QuantityBreakdown (MaterialID, ProductID, Quantity)
SELECT MaterialID, ProductID, SUM(Quantity)
FROM @Transactions
GROUP BY MaterialID, ProductID

답변:


1212

익명 유형을 사용하십시오.

예 :

group x by new { x.Column1, x.Column2 }

29
익명 유형으로 그룹화하는 것이 처음 인 경우이 예에서 'new'키워드를 사용하면 마술이됩니다.
Chris

8
nHibernate가있는 mvc의 경우 dll 문제에 대한 오류가 발생합니다. GroupBy (x => new {x.Column1, x.Column2}, (key, group) => new {Key1 = key.Column1, Key2 = key.Column2, Result = group.ToList ()});
밀라노

나는이 경우 새로운 객체가 참조로 비교할 것이라고 생각 했으므로 일치하지 않습니다.
HoGo

4
@HoGo 익명 형식의 개체 는 개체를 그룹화 할 때 사용되는 자체 Equals 및 GetHashCode 메서드를 구현 합니다.
바이런 Carasco

Linq를 처음 사용하는 경우 출력 데이터 구조를 시각화하기가 약간 어렵습니다. 익명 유형이 키로 사용되는 그룹을 작성합니까?
Jacques

760

절차 샘플

.GroupBy(x => new { x.Column1, x.Column2 })

어떤 유형의 객체가 반환됩니까?
mggSoft

5
익명 유형 인 @MGG_Soft
Alex

이 코드는 나를 위해 작동하지 않습니다 : "잘못된 익명 형식 선언자."
thalesfc

19
@Tom 이것이 작동하는 방식으로 작동합니다. 익명 형식의 필드 이름을 건너 뛰면 C #에서는 최종 액세스 한 속성 / 필드의 이름을 투영에서 사용한다고 가정합니다. (그래서 귀하의 예는 Mo0gles와 동일합니다)
Chris Pfohl

1
내 대답을 찾았습니다. Column1 및 Column2 속성을 포함하는 새 엔터티 (MyViewEntity)를 정의해야하며 반환 유형은 다음과 같습니다. IEnumerable <IGrouping <MyViewEntity, MyEntity >> 및 그룹화 코드 조각은 다음과 같습니다. MyEntityList.GroupBy (myEntity => new MyViewEntity {Column1 = myEntity. Column1, Column2 = myEntity.Column2});
Amir Chatrbahr

467

Ok 이것을 다음과 같이 얻었습니다.

var query = (from t in Transactions
             group t by new {t.MaterialID, t.ProductID}
             into grp
                    select new
                    {
                        grp.Key.MaterialID,
                        grp.Key.ProductID,
                        Quantity = grp.Sum(t => t.Quantity)
                    }).ToList();

75
+1-포괄적 인 예를 주셔서 감사합니다. 다른 답변의 스 니펫은 너무 짧으며 컨텍스트가 없습니다. 또한 집계 함수 (이 경우에는 Sum)를 표시합니다. 매우 도움이됩니다. 그룹화와 함께 집계 함수 (MAX, MIN, SUM 등)를 나란히 사용하는 것이 일반적인 시나리오라고 생각합니다.
barrypicker

여기에 : stackoverflow.com/questions/14189537/… , 그룹화가 이름이 알려진 단일 열을 기반으로 할 때 데이터 테이블에 표시되지만 그룹화를 기반으로하는 열을 수행하는 경우 어떻게 수행 할 수 있습니까? 동적으로 생성되어야합니까?
bg

이것은 그룹화의 개념을 이해하고 집계를 적용하는 데 실제로 도움이됩니다.
rajibdotnet

1
좋은 예 ... 내가 찾던 것. 나는 심지어 내가 람다를 찾고 있었지만 나는 내 필요를 해결하기에 충분하다는 것을 알았지 만 이것이 완전한 답이되도록 집계를 필요로했다.
Kevbo

153

여러 열로 그룹화하려면 대신 이것을 시도하십시오 ...

GroupBy(x=> new { x.Column1, x.Column2 }, (key, group) => new 
{ 
  Key1 = key.Column1,
  Key2 = key.Column2,
  Result = group.ToList() 
});

같은 방법으로 Column3, Column4 등을 추가 할 수 있습니다.


4
그것은 매우 도움이되었고 더 많은 투표를해야합니다! Result모든 열에 연결된 모든 데이터 세트를 포함합니다. 고마워요!
j00hi

1
참고 : ToList () 대신 .AsEnumerable ()을 사용해야했습니다.
GMan

1
정말 고마워요 여기 내 예가 있습니다. GetFees는 IQueryable <Fee> RegistryAccountDA.GetFees (registryAccountId, fromDate, toDate)를 반환합니다. .GroupBy (x => new {x.AccountId, x.FeeName}, (key, group) => new {AccountId = key.AccountId , FeeName = key.FeeName, AppliedFee = group.Sum (x => x.AppliedFee) ?? 0M}). ToList ();
Craig B

이 쿼리에서 그룹화되지 않은 다른 열을 가져 오는 것이 가능합니까? 객체 배열이있는 경우이 객체를 두 열로 그룹화하고 두 열뿐만 아니라 객체에서 모든 속성을 가져 오려고합니다.
FrenkyB


19

C # 7.1 이상 사용 Tuples하고 Inferred tuple element names(현재는에서만 작동 linq to objects과 표현의 나무는 예를 요구하는 경우는 지원되지 않습니다 someIQueryable.GroupBy(...). Github의 문제 ) :

// declarative query syntax
var result = 
    from x in inMemoryTable
    group x by (x.Column1, x.Column2) into g
    select (g.Key.Column1, g.Key.Column2, QuantitySum: g.Sum(x => x.Quantity));

// or method syntax
var result2 = inMemoryTable.GroupBy(x => (x.Column1, x.Column2))
    .Select(g => (g.Key.Column1, g.Key.Column2, QuantitySum: g.Sum(x => x.Quantity)));

다음을 사용하여 C # 3 이상anonymous types :

// declarative query syntax
var result3 = 
    from x in table
    group x by new { x.Column1, x.Column2 } into g
    select new { g.Key.Column1, g.Key.Column2, QuantitySum = g.Sum(x => x.Quantity) };

// or method syntax
var result4 = table.GroupBy(x => new { x.Column1, x.Column2 })
    .Select(g => 
      new { g.Key.Column1, g.Key.Column2 , QuantitySum= g.Sum(x => x.Quantity) });

18

강력한 형식의 그룹화에 Tuple <>을 사용할 수도 있습니다.

from grouping in list.GroupBy(x => new Tuple<string,string,string>(x.Person.LastName,x.Person.FirstName,x.Person.MiddleName))
select new SummaryItem
{
    LastName = grouping.Key.Item1,
    FirstName = grouping.Key.Item2,
    MiddleName = grouping.Key.Item3,
    DayCount = grouping.Count(), 
    AmountBilled = grouping.Sum(x => x.Rate),
}

4
참고 : 새로운 튜플을 만들기 Linq를하려면 엔티티에서 지원되지 않습니다
foolmoron

8

이 질문은 클래스 속성별로 그룹화를 요구하지만 DataTable과 같은 ADO 개체에 대해 여러 열로 그룹화하려면 "새"항목을 변수에 할당해야합니다.

EnumerableRowCollection<DataRow> ClientProfiles = CurrentProfiles.AsEnumerable()
                        .Where(x => CheckProfileTypes.Contains(x.Field<object>(ProfileTypeField).ToString()));
// do other stuff, then check for dups...
                    var Dups = ClientProfiles.AsParallel()
                        .GroupBy(x => new { InterfaceID = x.Field<object>(InterfaceField).ToString(), ProfileType = x.Field<object>(ProfileTypeField).ToString() })
                        .Where(z => z.Count() > 1)
                        .Select(z => z);

1
Linq 쿼리 "group c by new {c.Field <String> ("Title "), c.Field <String> ("CIF ")}"쿼리를 수행 할 수 없어서 많은 시간을 절약했습니다 !! 최종 쿼리는 "새 의한 그룹 C {titulo = c.Field <문자열> ("제목 "), CIF = c.Field <문자열> ("CIF ")}"
netadictos

4
var Results= query.GroupBy(f => new { /* add members here */  });

7
이전 답변에 아무것도 추가하지 않습니다.
Mike Fuchs

4
.GroupBy(x => x.Column1 + " " + x.Column2)

Linq.Enumerable.Aggregate()이것 과 결합 하면 동적 속성 수로 그룹화 할 수도 있습니다 propertyValues.Aggregate((current, next) => current + " " + next).
카이 하트만

3
이것은 누구보다 신용을주는 것보다 더 나은 대답입니다. column1에 column1에 추가 된 column1이 다른 상황에서 동일한 것과 동일한 조합의 인스턴스가있을 수 있으면 문제가 될 수 있습니다 ( "ab" "cde"는 "abc" "de"와 일치). 즉, 그룹 뒤에 람다를 별도의 식으로 미리 구성하기 때문에 동적 유형을 사용할 수 없으면 훌륭한 솔루션입니다.
Brandon Barkley

3
"ab" "cde"는 실제로 "abc" "de"와 일치하지 않아야하므로 그 사이에 공백이 있습니다.
Kai Hartmann

1
"abc de" ""및 "abc" "de"는 어떻습니까?
AlbertK

@AlbertK는 작동하지 않습니다.
카이 하트만



1

참고로 Lambda 표현식의 객체를 보내야하며 클래스의 인스턴스를 사용할 수 없습니다.

예:

public class Key
{
    public string Prop1 { get; set; }

    public string Prop2 { get; set; }
}

이것은 컴파일되지만 사이클 당 하나의 키 를 생성 합니다 .

var groupedCycles = cycles.GroupBy(x => new Key
{ 
  Prop1 = x.Column1, 
  Prop2 = x.Column2 
})

키 속성의 이름을 지정하지 않고 검색하면 대신 이와 같이 할 수 있습니다. 이것은 GroupBy올바르게하고 주요 속성을 제공합니다.

var groupedCycles = cycles.GroupBy(x => new 
{ 
  Prop1 = x.Column1, 
  Prop2= x.Column2 
})

foreach (var groupedCycle in groupedCycles)
{
    var key = new Key();
    key.Prop1 = groupedCycle.Key.Prop1;
    key.Prop2 = groupedCycle.Key.Prop2;
}

0

들어 VB익명 / 람다 :

query.GroupBy(Function(x) New With {Key x.Field1, Key x.Field2, Key x.FieldN })
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.