書籍転載:ASP.NET MVC 5 実践プログラミング
LINQ:データをグループ化する - group句[C#]
特定のキー列でデータをグループ化するためのgroup句/GroupByメソッドについて解説する。書籍転載の25本目(基礎編「5-3-8」)。
書籍転載について
本コーナーは、秀和システム発行の書籍『ASP.NET MVC 5 実践プログラミング』の中から、特にBuild Insiderの読者に有用だと考えられる項目を編集部が選び、同社の許可を得て転載したものです。
『ASP.NET MVC 5 実践プログラミング』の詳細や購入は秀和システムのサイトや目次ページをご覧ください。
ご注意
本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。
5-3-8 データをグループ化する - group句
特定のキー列でデータをグループ化するには、group句/GroupByメソッドを利用します。たとえば以下は、Articlesテーブルの内容をCategory列でグループ化し、それぞれに属する記事を列挙する例です(メソッド構文での記法も併記します)。
public ActionResult Group()
{
// 記事情報をカテゴリー単位にグループ化
var articles = from a in db.Articles
group a by a.Category;
// メソッド構文
// var articles = db.Articles.GroupBy(a => a.Category);
return View(articles);
}
|
1
2
3
1
5
6
7
2
9
10
11
12
|
@model IEnumerable<IGrouping<MvcModel.Models.CategoryEnum,MvcModel.Models.Article>>
... 中略 ...
<!-- グループを列挙 -->
@foreach (var group in Model) {
<dt>@group.Key</dt>
<dd>
<!-- グループに属するオブジェクトを列挙 -->
@foreach (var article in group) {
<p><a href="@article.Url">@article.Title</a></p>
}
</dd>
}
|
group句による戻り値は、IEnumerable<IGrouping<K, S>>
型です*35。よって、1では順番にグループを取得し、そのKeyプロパティでキー(ここではカテゴリー値)を取得します。グループ配下の要素(エンティティ)にアクセスするには、2のように取得したグループを更にループ処理します。
- *35
K
はキー、S
はエンティティの型です。
以下のようにすることで、Url/Title プロパティのみを含んだオブジェクトを返すこともできます。
public ActionResult Group2()
{
var articles =
from a in db.Articles
group new ArticleLinkView { Url = a.Url, Title = a.Title }
by a.Category;
// メソッド構文
//var articles = db.Articles.GroupBy(a => a.Category,
// a => new ArticleLinkView { Url = a.Url, Title = a.Title });
return View(articles);
}
|
- *36 対応するビューモデルArticleLinkView、ビュースクリプトGroup2.cshtmlは、配布サンプルを参照してください。
複数列でグループ化する
複数列(複合キー)でグルーピングするならば、以下のようにグループ化キーをオブジェクトとして指定します。サンプルは、Category/Published列でグループ化した例です。
public ActionResult MultiGroup()
{
var articles =
from a in db.Articles
group a by new ArticleGroup
{
Category = a.Category, Published = a.Published
};
// メソッド構文
//var articles = db.Articles.
// GroupBy(a => new ArticleGroup
// {
// Category = a.Category, Published = a.Published
// });
return View(articles);
}
|
- *37 対応するビューモデルArticleGroup、ビュースクリプトMultiGroup.cshtmlは、配布サンプルを参照してくださ い。
その他、(たとえば)太字の部分をa.Published.Year
のようにすることで、公開「年」でグループ化したり、a.Title[0]
でタイトルの先頭文字でグループ化したりすることもできます。はたまた、a.Viewcount == 0 ? 0 : a.Viewcount / 10000
のような式を利用することで、0~10000、10001~20000...の単位でグループ化することも可能です。
グループ化した結果でフィルターする
intoキーワードを利用することで、グルーピングされた結果に対して、追加でフィルターすることも可能です。いわゆるSQL-SELECT命令のHAVING句に相当するコードです。
public ActionResult Having()
{
var articles =
from a in db.Articles
group a by a.Category into cgroup
where cgroup.Average(a => a.Viewcount) > 10000
select new ArticleHaving
{
Category = cgroup.Key,
ViewAverage = cgroup.Average(a => a.Viewcount)
};
// メソッド構文
//var articles = db.Articles.GroupBy(a => a.Category)
// .Where(group => group.Average(a => a.Viewcount) > 10000)
// .Select(group => new ArticleHaving
// {
// Category = group.Key,
// ViewAverage = group.Average(a => a.Viewcount)
// });
return View(articles);
}
|
- *38 対応するビューモデルArticleHaving、ビュースクリプトHaving.cshtmlは、配布サンプルを参照してください。
intoキーワードでグループ化の結果を一時的に格納しておき、その結果でもってwhere/select句を呼び出しているわけです。メソッド構文では、以降のWhere/Selectメソッドには無条件にグループ化の結果が渡されますので、それと意識することなく絞り込みの式を表現できます。
Averageメソッドは集計メソッドで、その他にも以下のようなものを利用できます。
メソッド | 概要 |
---|---|
Average | 平均値 |
Count | 件数 |
LongCount | 件数(Int64型) |
Max | 最大値 |
Min | 最小値 |
Sum | 合計値 |
同じ要領で、グループキーでソートすることもできます。
public ActionResult Having2()
{
var articles = from a in db.Articles
group a by a.Category into cgroup
orderby cgroup.Key.ToString()
select cgroup;
// メソッド構文
//var articles = db.Articles
// .GroupBy(a => a.Category)
// .OrderBy(group => group.Key.ToString());
return View(articles);
}
|
- *39 対応するビュースクリプトHaving2.cshtmlは、配布サンプルを参照してください。
※以下では、本稿の前後を合わせて5回分(第23回~第27回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
23. LINQ:特定範囲のデータだけを取得する - Skip/Takeメソッド[C#]
指定された件数だけデータを読み飛ばすためのSkipメソッドと、指定された件数のデータだけを取得するためのTakeメソッドについて解説。書籍転載の23本目(基礎編「5-3-6」)。
24. LINQ:先頭のデータを取得する - Firstメソッド[C#]
クエリ後の結果セットから先頭のデータを取得するためのFirstメソッドについて解説する。書籍転載の24本目(基礎編「5-3-7」)。
25. 【現在、表示中】≫ LINQ:データをグループ化する - group句[C#]
特定のキー列でデータをグループ化するためのgroup句/GroupByメソッドについて解説する。書籍転載の25本目(基礎編「5-3-8」)。
26. LINQ:エンティティ同士を結合する - join句[C#]
特定のキー列でエンティティ同士を結合し、複数のエンティティをまとめて取得するためのjoin句/Joinメソッドについて解説する。書籍転載の26本目(基礎編「5-3-9」)。
27. 開発者に人気のCSSフレームワーク「Bootstrap」入門
「レスポンシブデザインに対応したグリッドシステム」などの特長で、特に開発者に人気のCSSフレームワーク「Bootstrap」について解説する。書籍転載の27本目(応用編「8-2-5」)。転載は今回で終了。