共通するキー項目を元にローカルでデータテーブルを結合させたい場面が稀にあります。そんな時はリレーションを貼って処理するのですが、どこもかしこも内部結合(INNER JOIN)の記事しか無かったので外部結合のやり方について纏めてみた。
データセットのリレーションを使う
Relationsプロパティを使うと異なるテーブル同士をリンクさせ、リレーションシップのコレクションが取得されます。
要は外部結合や内部結合が簡単に出来まっせって話。
勿論データを持ってくる段階のSQL等でJOINさせるのが一番ベストなのは間違い無いんですけども、異なる二つのCSVを取り込む時とか、テンポラリにINSERTとかするまでも無いみたいな、そんな状況の時に大活躍します。
DtMaster
ID | 名前 |
1 | あほあほ |
2 | ほげほげ |
3 | ふがふが |
DtTransaction
出退勤 | 時刻 | ID | 名前 |
出勤 | 10:00 | 1 | |
出勤 | 10:02 | 2 | |
早退 | 15:00 | 5 |
今回は上記の様なデータテーブルが合ったとして、DtTransactionの名前欄にマスタから引っ張った名前を付与して返したいとします。DtTransactionの全データと、IDで紐づくDtMasterの名前 なのでLEFT JOIN(左外部結合)です。
構文:dataset.Relations.Add(リレーション名,親テーブル項目,子テーブル項目,制約有無)
Relationsプロパティの特に気を付けるべきなのが第4引数の制約。
省略するとtrue扱いになり勝手に制約が設けられてしまう(今回の様にLEFT JOINを行うとエラーが吐かれる)ので、適宜使い分けの必要有り。
データテーブル結合処理
一連の流れはこんな感じ。
// 結合用データセット
DataSet ds = new DataSet();
ds.Tables.Add(DtMaster.Copy());
ds.Tables[ds.Tables.Count - 1].TableName = "マスタ";
ds.Tables.Add(DtTransaction.Copy());
ds.Tables[ds.Tables.Count - 1].TableName = "トランザクション";
DataRow[] ChildRow;
int nRecordCnt = 0;
// リレーションを貼る
// 今回はDtTransactionに値を付与した結果が欲しいのでDtTransactionを親とする
ds.Relations.Add("結合情報",
ds.Tables["トランザクション"].Columns["ID"],
ds.Tables["マスタ"].Columns["ID"], false);
// DtTransactionレコード分ループ
foreach (DataRow row in ds.Tables["トランザクション"].Rows)
{
// 子要素取得
ChildRow = row.GetChildRows("結合情報");
// 結合されていた場合
if (ChildRow.Length != 0)
{
// 会社名称格納
ds.Tables["トランザクション"].Rows[nRecordCnt]["名前"] = ChildRow[0]["名前"].ToString();
nRecordCnt++;
continue;
}
nRecordCnt++;
}
リレーション実行結果
上記実行するとこうなる↓
コメント