|
|
連載:[完全版]究極のC#プログラミング
Chapter15 LINQとクエリ式
川俣 晶
2010/03/17 |
|
|
15.17 join句のグループ化結合
join句には「内部結合」のほかに、「グループ化結合」と「左外部結合」が存在する。続けて、この2つを見ていこう。
内部結合は、2つのソースに一致する値を見い出した時点で、続きのクエリを発動できた。たとえば、「ID番号と商品名を持つソース」と「ID番号と価格を持つソース」を使い、ID番号で内部結合を行えば、商品名とそれに対応する価格を結び付けることができた。
しかし、この機能は場合によっては十分ではない。同じ商品を異なる店舗で別の価格で販売している場合、商品名に対する価格は複数になってしまう。さらに、価格ごとに「どの店での値段か」という情報も添えなければならない。
このようなケースでは、「内部結合」ではなく「グループ化結合」を使用するとよい。グループ化結合は、join句で結合の対象となる2つのソースのうち、左側のソースの要素が、右側のソースに含まれる1つ以上の一致する要素に関連付けられる。
つまり、このケースでは次のような関連付けが行われる。
商品名 => ((店名, 価格), (店名, 価格), ……)
|
|
実際にこれを記述した例を、次ページのリスト15.21に示す。
using System;
using System.Linq;
class Program
{
class 商品情報
{
public int Id;
public string 名前;
}
class 商品販売価格
{
public int Id;
public int 価格;
public string 店名;
}
static void Main(string[] args)
{
商品情報[] 商品情報データ =
{
new 商品情報() { Id = 1, 名前="PC-8001" },
new 商品情報() { Id = 2, 名前="MZ-80K" },
new 商品情報() { Id = 3, 名前="Basic Master Level-3" },
};
商品販売価格[] 商品販売価格データ =
{
new 商品販売価格() {Id=1, 価格=168000, 店名="BitOut"},
new 商品販売価格() {Id=1, 価格=148000, 店名="富士山音響"},
new 商品販売価格() {Id=2, 価格=178000, 店名="富士山音響"},
new 商品販売価格() {Id=3, 価格=298000, 店名="マイコンセンターROM"},
new 商品販売価格() {Id=3, 価格=229000, 店名="富士山音響"},
};
var query = from x in 商品情報データ
join y in 商品販売価格データ
on x.Id equals y.Id into z
select new { Name = x.名前, 商品データ = z };
foreach (var 商品 in query)
{
Console.WriteLine("{0}", 商品.Name);
foreach (var 価格情報 in 商品.商品データ)
{
Console.WriteLine("\t{0} {1:C}",
価格情報.店名, 価格情報.価格);
}
}
}
}
|
|
リスト15.21 グループ化結合の例 |
PC-8001
BitOut \168,000
富士山音響 \148,000
MZ-80K
富士山音響 \178,000
Basic Master Level-3
マイコンセンターROM \298,000
富士山音響 \229,000
|
|
リスト15.21の実行結果 |
このように、1つの商品名に対して、複数の「店名+価格」情報が関連付けられた。
さて、「内部結合」では次の書式が使用された。
join 〜 in 〜 on 〜 equals 〜
|
|
join句による内部結合の構文 |
これに対して、グループ化結合では次のように「intoキーワード」が追加されてさらに長くなる(この“into”はinto句ではなく、join-into構文と呼ばれるものの一部。厳密には、join句には、intoを持たないjoin構文とjoin-into構文の2種類が存在する)。
join 〜 in 〜 on 〜 equals 〜 into 〜
|
|
join句によるグループ化結合の構文 |
intoキーワードの役割は、equalsキーワードで指定された条件を満たす右側のソースの要素をグループ化することである。左側のソースの要素が同じものごとに、グループ分けが行われる。
たとえば、リスト15.21では「into z」と書かれているが、このzにグループ分けされたグループが格納されている。これはselect句によって、「商品データ = z」のように参照して利用できる。実際、次のforeach文で利用されている。
foreach (var 価格情報 in 商品.商品データ)
|
|
つまり、グループ化結合は、グループごとに結合された値の集まりを列挙する。すべて列挙するには、階層化された二重の繰り返し(列挙)を必要とする。このようにすれば、(リスト15.21の)実行結果に見られるような階層化された結果を得るために使用できる。
Insider.NET 記事ランキング
本日
月間