質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

JOIN

これはSQL文のJOINに関するタグです。リレーショナルデータベースシステムの二つ以上のテーブルを結合する際に、この構文が利用されます。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

Q&A

1回答

5931閲覧

DataTableをLINQで結合した結果を列名指定せず一括でSELECTした結果を取得したい

hagi_moge

総合スコア12

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

JOIN

これはSQL文のJOINに関するタグです。リレーショナルデータベースシステムの二つ以上のテーブルを結合する際に、この構文が利用されます。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

1グッド

3クリップ

投稿2020/03/12 08:07

編集2020/03/12 08:19

実現したいこと

2つのDataTableを受け、LINQを用いて特定のキーで外部結合し、SQLのSELECT *に相当する結果をDataTableで返す関数を実装したいです。
DataTableは任意のCSVを読み込んで作成するので、LINQメソッド内でSELECTするカラム名を指定できないため、このような質問をさせて頂きました。

現状

下記質問を参考に内部結合は実装できたのですが、
https://teratail.com/questions/131794
外部結合するためのGroupJoinの使うまでは分かったのですが、正解の実装方法がわからない状態です。

C#

1public class Program 2{ 3 static void Main(string[] args) 4 { 5 // 結合されるデータテーブル 6 DataTable dtX = new DataTable(); 7 dtX.Columns.Add("key", typeof(string)); 8 dtX.Columns.Add("valX", typeof(double)); 9 dtX.Rows.Add("AAA", 1); 10 dtX.Rows.Add("BBB", 2); 11 dtX.Rows.Add("CCC", 3); 12 13 // 結合するデータテーブル 14 DataTable dtY = new DataTable(); 15 dtY.Columns.Add("key", typeof(string)); 16 dtY.Columns.Add("valY", typeof(int)); 17 dtY.Columns.Add("valYY", typeof(int)); 18 dtY.Rows.Add("AAA", 10, 11); 19 dtY.Rows.Add("BBB", 20, 22); 20 21 // 結合実行 22 GetJoinedDataTable(dtX, dtY); 23 } 24 25 // 結合メソッド 26 public static DataTable GetJoinedDataTable(DataTable dtFrom, DataTable dtJoin) 27 { 28 DataTable dtResult = new DataTable(); 29 foreach (DataColumn column in dtFrom.Columns) 30 { 31 dtResult.Columns.Add("from." + column.ColumnName, typeof(string)); 32 } 33 foreach (DataColumn column in dtJoin.Columns) 34 { 35 dtResult.Columns.Add("join." + column.ColumnName, typeof(string)); 36 } 37 38 var methodQ = dtFrom.AsEnumerable().Join( 39 dtJoin.AsEnumerable(), 40 f => f["key"], 41 j => j["key"], 42 (f, j) => 43 { 44 DataRow row = dtResult.NewRow(); 45 row.ItemArray = f.ItemArray.Concat(j.ItemArray).ToArray(); 46 dtResult.Rows.Add(row); 47 return row; 48 }); 49 50 return methodQ.CopyToDataTable(); 51 } 52}

一応m外部結合用メソッド実装tryしてみたのですが、
結合するデータテーブルに1つでもキーが不足している場合(結合結果カラムの値がNULLになる場合)正しいデータテーブルで結果が帰ってきません。

DataTable dtResult = new DataTable(); foreach (DataColumn column in dtFrom.Columns) { dtResult.Columns.Add("from." + column.ColumnName, typeof(string)); } foreach (DataColumn column in dtJoin.Columns) { dtResult.Columns.Add("join." + column.ColumnName, typeof(string)); } var methodQ = dtFrom.AsEnumerable().GroupJoin( dtJoin.AsEnumerable(), f => f["key"], j => j["key"], (f, tmpj) => new { f = f, tmpj = tmpj }) .SelectMany ( x => x.tmpj.DefaultIfEmpty(), (x, j) => { DataRow row = dtResult.NewRow(); row.ItemArray = x.f.ItemArray.Concat(j.ItemArray).ToArray(); dtResult.Rows.Add(row); return row; } );

実装できる方おられましたら、どうかお力添えお願い致します。

s.k👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

とりあえずは左テーブルにキーがあり、右テーブルにキーがないパターン(key:CCC)の時に、
SelectMany内のDataRow型j変数自体がnullになっているため、
NullReferenceExceptionとなっていますね。
なのでnull時に空のObject配列を作っておけば回避はできます。
ただもっと美しく書けるやり方とかは分からないです。
ひとまずエラー回避ということで。

C#

1var methodQ = dtFrom.AsEnumerable().GroupJoin( 2 dtJoin.AsEnumerable(), 3 f => f["key"], 4 j => j["key"], 5 (f, tmpj) => new 6 { 7 f = f, 8 tmpj = tmpj 9 }) 10 .SelectMany 11 ( 12 x => x.tmpj.DefaultIfEmpty(), 13 (x, j) => 14 { 15 DataRow row = dtResult.NewRow(); 16 // jがnull時に空のObject配列を作っておく 17 Object[] oJoin = j == null ? new Object[0] : j.ItemArray; 18 row.ItemArray = x.f.ItemArray.Concat(oJoin).ToArray(); 19 dtResult.Rows.Add(row); 20 return row; 21 } 22 );

投稿2020/03/13 02:06

編集2020/03/13 02:12
yureighost

総合スコア2183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問