Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9567

グループごとに列の最大値を持つレコードの抽出

$
0
0
はじめに 先日業務にて表題の件について調べたので共有します。 本記事は LINQ to Entities にて、テーブルデータをグルーピングしたのち、グループごとに列の最大値を持つレコードを抽出するという内容となっています。 本題 例えば下の表のように元テーブルのデータをName列でグルーピングし、グループごと(Nameごと)にScore列の最大値を持つレコードを抽出したい場合を想定します。 元テーブル Id Name Score Age 1 taro 60 20 2 hanako 90 19 3 hanako 50 19 4 taro 100 20 5 jiro 70 22 抽出したいデータ Name Score Age hanako 90 19 taro 100 20 jiro 70 22 SQL Server で書いた場合 サブクエリではGroupBy句によりName列でグルーピングし、Max関数によりグループごとのScore列の最大値を取得します。 メインクエリではサブクエリで取得したScore値を持つレコードを抽出します。 qiita.sql Select Name, Score, Age From Table1 As T1 /* メインクエリ */ Where Score = ( Select Max(Score) From Table1 /* サブクエリ */ Group By Name Having Name = T1.Name ); LINQ to Entities で書いた場合 group句でName列とAge列でグルーピングした結果を G1 に格納します。 select句でName列、Score列、Age列を持つ新しいオブジェクトを作成します。 Score列にはサブクエリにて取得した、グループごとにScore列の最大値を持つレコードを格納します。 ※ T は任意のデータ型 qiita.cs 1: List<T> record = (from T1 in db.Table1 2: group T1 by new { /* グルーピングのKey要素にName列とAge列を追加 */ 3: NAME = T1.Name, 4: AGE = T1.Age 5: } into G1 /* グルーピング後のデータセットをG1に格納する */ 6: select new { 7: Name = G1.Key.NAME, 8: Score = (from T2 in G1 select T2.Score).Max(), /* サブクエリにてグループごとにScore列の最大値を持つレコードを抽出 */ 9: Age = G1.Key.AGE 10: }).ToList(); 補足 2行目の group句 の戻り値は IGrouping<TKey, TElement> のオブジェクトとなる。 6行目の select句 の戻り値は IQueryable<IGrouping<TKey, TElement>> のオブジェクトとなる。 10行目の ToListメソッド の戻り値は List<T> のオブジェクトとなる。 3, 4行目でグルーピングの Key要素に Name列と Age列を指定したことで、T1 は Name列, Age列でグルーピングされます。 また、7, 9行目のように TKey を指定することで TElement にアクセスすることができます。 ちなみに group句 の Key要素 に Name列のみ を指定した場合、TKey を指定してアクセスできる TElement は Name列のみ となります。 また、IGrouping<TKey, TElement> のオブジェクトは基本的に二重リストで実現されているため、各グループのアイテムにアクセスするには二重ループによって反復処理する必要があります。 ※以下のプログラムではデータセットのグルーピングのみを実装しています。 qiita.cs 1: var record = from T1 in db.Table1 2: group T1 by T1.Name 3: into G1 4: select G1; 5: 6: foreach(var itemKey in record) 7: { 8: foreach(var item in itemKey) 9: { 10: Console.WriteLine("{0} {1} {2}", item.Name, item.Score, item.Age); 11: // item.Name は itemKey.key としてもアクセスできます 12: } 13: } 14: 15: // OutPut 16: // taro 60 20 17: // hanako 90 19 18: // hanako 50 19 19: // taro 100 20 20: // jiro 70 22 さいごに 今回の記事内容に対して至らない点がありましたら、ご指摘いただけると幸いです。 最後までお読みいただきありがとうございました。 また逢う日まで。 参考文献

Viewing all articles
Browse latest Browse all 9567

Trending Articles