C#ライブラリリファレンス - 2つのデータの集合を外部結合する
Enumerable静的クラスのGroupJoin拡張メソッドは、2つのデータ集合を、外部結合することができます。
日常でたとえると
商品表と売上明細表のデータを合体する。ただし、売り上げがない商品も書いておく。
使用に適した状況
2つ以上のデータ集合を、片方に存在しないデータも含めつつ結合したい場合。
サンプル
/*----------------------------------------------------
*
* データの集合を外部結合する
*
----------------------------------------------------*/
using System;
using System.Linq;
class Sample
{
class Product
{
public int ID { get; set; }
public string Name { get; set; }
public Product( int id, string name )
{
this.ID = id;
this.Name = name;
}
public override string ToString( )
{
return String.Format(
"{0}( ID : {1})",
this.Name, this.ID );
}
}
class SalesDetails
{
public DateTime Date { get; set; }
public int ProductId { get; set; }
public int Count { get; set; }
public SalesDetails( DateTime date, int id, int count )
{
this.Date = date;
this.ProductId = id;
this.Count = count;
}
public override string ToString( )
{
return String.Format(
"売上日:{0} 商品ID「{1}」 数量={2}",
this.Date, this.ProductId, this.Count );
}
}
static void Main( )
{
//データソースを用意
var products = new[ ] {
new Product( 1, "釘"),
new Product( 2, "金槌"),
new Product( 3, "ペンチ")
};
var values = new[ ] {
new SalesDetails (
new DateTime( 2014, 4, 10) ,
1,
2 ) ,
new SalesDetails (
new DateTime( 2014, 6, 8) ,
2,
1 ) ,
new SalesDetails (
new DateTime( 2014, 6, 9 )
, 1,
1 )
};
Console.WriteLine( "データ" );
foreach ( var v in products )
Console.WriteLine( "{0} ", v );
Console.WriteLine( Environment.NewLine );
foreach ( var v in values )
Console.WriteLine( "{0} ", v );
Console.WriteLine( Environment.NewLine );
//データを左外部結合
Console.WriteLine(
"データを左外部結合します・・・" );
var results = products.GroupJoin(
values,
x => x.ID,
y => y.ProductId,
( x, sales ) =>
new { x.Name, x.ID, sales } );
foreach ( var x in results ) {
Console.WriteLine(
"{0}( ID:{1} )",
x.Name, x.ID );
foreach ( var y in x.sales )
Console.WriteLine( "\t{0} ", y );
}
Console.WriteLine( Environment.NewLine );
//クエリ式でデータを左外部結合
Console.WriteLine( "クエリ式を使用します・・・" );
var qr1 =
from p in products
join s in values
on p.ID equals s.ProductId
into sales
select new { p.Name, p.ID, sales };
foreach ( var x in qr1 ) {
Console.WriteLine(
"{0}( ID:{1} )",
x.Name, x.ID );
foreach ( var y in x.sales )
Console.WriteLine( "\t{0} ", y );
}
Console.WriteLine( Environment.NewLine );
//入れ子構造のクエリ式でデータを左外部結合
Console.WriteLine( "クエリ式を使用します・・・" );
var qr2 =
from p in products
join s in
(
from s in values
select s
) on p.ID equals s.ProductId
into sales
select new { p.Name, p.ID, sales };
foreach ( var x in qr2 ) {
Console.WriteLine(
"{0}( ID:{1} )",
x.Name, x.ID );
foreach ( var y in x.sales )
Console.WriteLine( "\t{0} ", y );
}
Console.WriteLine( Environment.NewLine );
//終了
Console.WriteLine( "サンプル終了。" );
Console.ReadLine();
}
}
名前空間
Sytem.Linq名前空間を参照してください。
解説
複数のデータを扱う集合指向プログラミングでは、2つ以上のデータ集合を結合することがよくあります。例えば、商品データ集合と、売上明細データ集合を組み合わせると、商品に関する情報がある売上明細情報になります。
ところで、指定した範囲内に売上がない商品のデータはどうなるのでしょうか?そのデータは含めます。GroupJoin拡張メソッドとJoin拡張メソッドの違いはここで、階層化されて射影します。
もしかしたら、2つのデータ集合を組み合わせるという行為の有用性が分かり難いかもしれません。その効果を理解するには、データベースとリレーショナル理論を学べば、すぐにわかります。この機会に、データベースとリレーショナル理論を学ぶとよいでしょう。