【C#】ローカルでデータテーブルを外部結合させる

C#

共通するキー項目を元にローカルでデータテーブルを結合させたい場面が稀にあります。そんな時はリレーションを貼って処理するのですが、どこもかしこも内部結合(INNER JOIN)の記事しか無かったので外部結合のやり方について纏めてみた。

スポンサーリンク

データセットのリレーションを使う

Relationsプロパティを使うと異なるテーブル同士をリンクさせ、リレーションシップのコレクションが取得されます。
要は外部結合や内部結合が簡単に出来まっせって話。

勿論データを持ってくる段階のSQL等でJOINさせるのが一番ベストなのは間違い無いんですけども、異なる二つのCSVを取り込む時とか、テンポラリにINSERTとかするまでも無いみたいな、そんな状況の時に大活躍します。

DtMaster

ID名前
1あほあほ
2ほげほげ
3ふがふが

DtTransaction

出退勤時刻ID名前
出勤10:001
出勤10:022
早退15:005

今回は上記の様なデータテーブルが合ったとして、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++;
            }

リレーション実行結果

上記実行するとこうなる↓

コメント