841

LINQでGroupBy Multiple Columnsを実行する方法

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

12 답변


1083

匿名型を使用してください。

例えば

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


  • 匿名型を使用したグループ化に慣れていない場合は、[新しい]を使用します。この例のキーワードは魔法をします。 - Chris
  • nHibernateのmvcがdllの問題でエラーを起こしている場合。 GroupBy(x => new {x.Column1、x.Column2}、(key、group)=> new {Key1 = key.Column1、Key2 = key.Column2、Result = group.ToList()}によって問題が解決されました; - Milan
  • この場合、新しいオブジェクトは参照によって比較されるので、一致しない - グループ化されていないと考えました。 - HoGo
  • @HoGo匿名型付きオブジェクト独自のEqualsとGetHashCodeを実装するオブジェクトをグループ化するときに使用されるメソッド。 - Byron Carasco
  • Linqを初めて使用するときに、出力データ構造を視覚化するのは少し難しいです。これは匿名タイプがキーとして使用されるグループ化を作成しますか? - Jacques

661

手続きサンプル

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


  • オブジェクトはどのタイプのものを返しますか? - mggSoft
  • 匿名型になる@MGG_Soft - Alex
  • 構文がわずかにずれているため、'無効な匿名型宣言子が表示されます。.GroupBy(x => new {Column1 = x.Column1、Column2 = x.Column2}) - Tom Maher
  • @Tomこれはそれなりにうまくいくはずです。匿名型C#のフィールドの命名をスキップすると、最後にアクセスしたプロパティ/フィールドの名前を射影から使いたいと想定します。 (つまり、あなたの例はMo0gles'と同等です。) - Crisfole
  • 私の答えを見つけた。 Column1プロパティとColumn2プロパティを含む新しいエンティティ(MyViewEntity)を定義する必要があります。戻り値の型は次のとおりです。IEnumerable< IGrouping< MyViewEntity、MyEntity>> MyEntityList.GroupBy(myEntity => new MyViewEntity {Column1 = myEntity.Column1、Column2 = myEntity.Column2});そして、グループ化コードは次のとおりです。 - Amir Chatrbahr

431

わかりました:

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


  • +1 - 包括的な例をありがとう。もう1つの回答の抜粋は短すぎて、文脈がありません。また、集約関数(この場合はSum)を表示します。非常に役立ちます。集約関数(つまり、MAX、MIN、SUMなど)をグループ化と並べて使用するのが一般的なシナリオであると思います。 - barrypicker
  • ここに :stackoverflow.com/questions/14189537/…グループ化が名前が知られている単一の列に基づいているとき、それはデータテーブルのために示されています、しかしグループ化がされることに基づいている列が動的に生成されなければならないならどうすればそれができますか? - b.g
  • これは、グループ化の概念を理解し、その上に集約を適用するのに非常に役立ちます。 - rajibdotnet
  • 良い例...私が探していたものだけ。私は私が私のニーズを解決するためにそれから十分に得たラムダを探していたとしても、これは完璧な答えでした。 - Kevbo

128

複数列でグループ化する場合は、代わりにこれを試してください...

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

同じ方法でColumn3、Column4などを追加できます。


  • それはとても役に立ち、もっと多くの支持を得るでしょう!Resultすべての列にリンクされているすべてのデータセットを含みます。どうもありがとう! - j00hi
  • 注:ToList()の代わりに.AsEnumerable()を使用しなければなりませんでした - GMan
  • 素晴らしい、これをありがとう。これが私の例です。 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)?? 0 M})。ToList(); - Craig B
  • このクエリからグループ化されていない他の列を取得することは可能ですか。オブジェクトの配列がある場合は、このオブジェクトを2列でグループ化しますが、これら2列だけではなく、すべてのプロパティをオブジェクトから取得します。 - FrenkyB

18

C#7以降、値タプルも使用できます。

group x by (x.Column1, x.Column2)

または

.GroupBy(x => (x.Column1, x.Column2))


  • まあ、私はあなたが最後に余分なものを見逃していると思います。あなたは()を閉じていません - StuiterSlurf
  • 追加しました。 - Nathan Tregillus
  • .GroupBy(x => new {x.Column1、x.Column2}) - Zahidul Islam Jamy

16

強く型付けされたグループ化には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),
}


  • 注意:新しいタプルの作成は、Linq To Entitiesではサポートされていません。 - 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);


  • Linqクエリ「group by c by new {c.Field< String>(" Title>)、c.Field< String>(< CIF")}」を実行できず、保存しました多くの時間!!最終的なクエリは、「グループc by新しい{titulo = c。フィールド<文字列>( "タイトル")、cif = c。フィールド<文字列>( "CIF")}」でした。 - netadictos

5

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


  • 前の答えには何も追加しません。 - Mike Fuchs

2

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


  • と組み合わせLinq.Enumerable.Aggregate()これにより、動的な数のプロパティによるグループ化も可能になります。propertyValues.Aggregate((current, next) => current + " " + next)。 - Kai Hartmann
  • これは誰もが信用しているよりも良い答えです。 column1がcolumn2と異なる状況で同じことがcolumn2に追加された組み合わせと同じである場合がある(「ab」「cde」が「abc」「de」と一致する)場合がある場合、それは問題となる可能性があります。とは言っても、動的型を使用できない場合、これは素晴らしい解決策です。グループの後にラムダを別の式で作成するからです。 - Brandon Barkley
  • " ab" " cde" " abc"と実際には一致しないはずです。 「de」、したがってその間の空白です。 - Kai Hartmann

2

xをnew {x.Col、x.Col}でグループ化


2

.GroupBy(x => (x.MaterialID, x.ProductID))


  • このコードが問題を解決する方法についての説明を追加することを検討してください。 - Rosário Pereira Fernandes
  • これは質問に対する答えを提供しません。著者からの批評または説明を要求するために、彼らの投稿の下にコメントを残してください。 - レビューから - Mamun

0

注意しなければならないのは、Lambda式にはオブジェクトを送信する必要があり、クラスにはインスタンスを使用できないということです。

例:

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

    public string Prop2 { get; set; }
}

これはコンパイルしますが生成しますサイクルごとに1つのキー

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;
}

リンクされた質問


関連する質問

最近の質問