2017-03-01 16 views
1

2つの異なるソースからデータを取得する2つのデータテーブルがあります。私は、Table2の行が一致しないだけのTables1行を持つ新しいDataTable Table3を作成したいと考えています。私の2つのDataTableは、以下に示すように異なる構造を持っています。ただし、それらはすべて同じプライマリキー(CarReg)を共有します。したがって、CarReg列を使用して行を比較し、Table1ではなくTable2にあるすべての行を戻したいと考えています。返されたTable3 DataTableは、Table1と同じ構造になります。2つのデータテーブルを比較し、2番目のテーブルにない最初のテーブルレコードを選択します。

私は以下を試しましたが、最初の表Table1からすべてのレコードを取得しています。私はTable1にあるレコードだけを取得する必要がありますが、Table2にはありません。たとえば、Table1に20個のレコードがあり、Tables2に15個のレコードがある場合は、5個のレコードしか必要としません。助けてください。

var recordsNotInB = TableA.AsEnumerable().Select(r =>r.Field<string>("CarReg").Except(TableB.AsEnumerable().Select(r => r.Field<string>("CarReg"))); 
+0

Table2の一致するCarRegを持たないTable1のすべてのレコードが必要ですか? –

+0

@ YawarMurtazaはい、Table2の一致するCarRegを持たないTable1のすべてのレコードが必要です。これを簡単な英語の文章で指定していただきありがとうございます。 –

答えて

1

これ以上のコードを知っていると、私はこれを思いつきます。

var idsFromTableB = TableB.AsEnumerable().Select(tb => tb.Field<string>("CarReg")); 
var recordsNotInB = TableA.AsEnumerable().Where(ta => !idsFromTableB.Contains(ta.Field<string>("CarReg"))); 
+0

私は自分のコードで取得したものと同じ数のレコードを取得しています。つまり、最初のテーブルTableAにすべてのレコードを取得しています。私はTableAではなくTableBであるレコードを取得する必要があります。それ以外の場合は、お返事ありがとう –

+0

ありがとう、私は正しく来ることができた。なぜなら、私は文字列フィールドの列を扱っていたので、比較のために両方のテーブルで値をトリムする必要がありました。もう一度ありがとうございます。 –

0

あなたは、次のコードスニペットでそれを試すことができます。

 var result = new List<DataRow>(); 
     //convert to list to avoid multiple enumerations 
     var table2List = Table2.AsEnumerable().ToList(); 

     foreach(var row in Table1.AsEnumerable()) 
     { 
      var matchingRow = table2List.FirstOrDefault(x => x["CarReg"] == row["CarReg"]); 

      if(matchingRow == null) 
      { 
       result.Add(row); 
      } 
     } 

あなたはCarRegフィールドに基づいて表2に含まれていない表1からでDataRowのコレクションを取得する必要があります。

+0

これは私のために働いていません。このコードは実際にはより多くのレコードを返します - デカルト製品のようなものです。明らかにするために、Table1とTable2は同じ基本構造を持っています。したがって、Table1の1つのレコードは、Table2に1回しか存在しない場合に発生します。したがって、私の場合、現在Table1にあるすべてのレコードが必要ですが、レコード(プライマリキー "CarReg"のため)はまだTable2にありません –

+0

要求したタスクを達成できるはずの変更を追加しました。 –

1

パフォーマンスを向上させ、ハッシュセットを使用して比較方法を指定することもできます。

var idsFromTableB = new HashSet<string>(TableB.AsEnumerable() 
    .Select(tb => tb.Field<string>("CarReg")), StringComparer.OrdinalIgnoreCase); 

var recordsNotInB = TableA.AsEnumerable() 
    .Where(ta => !idsFromTableB.Contains(ta.Field<string>("CarReg"))); 
0

これは長年にわたる解決策ですが、私はそれをテストして動作します。

私は、各テーブルのPOCOオブジェクトを作成してから、エラーの可能性が高いTable1 ["CarReg"]を使用するよりもパブリックプロパティでの再生が容易であるようにdifneceを作成しました。

誰かがこの解決方法を改善する可能性があります。

あなたのテーブルは次のようにPOCOクラスで表現されるようにしましょう:データを取り込むことができます

public class Table1 
{ 
    public string CarReg { get; set; } 
    public string Site { get; set; } 
    public double Route { get; set; } 
    public string Driver { get; set; } 
    public string DateString { get; set; } 
} 

public class Table2 
{ 
    public string CarReg { get; set; } 
    public string Site { get; set; } 
    public double Route { get; set; } 
    public string Driver { get; set; } 
    public string Kilos { get; set; } 
} 

IEnumerable<Table1> data1 = new List<Table1>() 
      { 
       new Table1() { CarReg = "123ABC", DateString = "20/02/2018", Driver = "Driver 1", Route = 45.45, Site = "England" }, 
       new Table1() { CarReg = "456ABC", DateString = "20/03/2018", Driver = "Driver 2", Route = 55.45, Site = "Scotland" }, 
       new Table1() { CarReg = "789ABC", DateString = "20/04/2018", Driver = "Driver 3", Route = 65.45, Site = "Wales" }, 
      }; 

      IEnumerable<Table2> data2 = new List<Table2>() { 
       new Table2() { CarReg = "123XYZ", Kilos = "34KG", Driver = "Driver 5", Route = 45.45, Site = "Karachi" }, 
       new Table2() { CarReg = "456ABC", Kilos = "44KG", Driver = "Driver 2", Route = 55.45, Site = "Scotland" }, 
       new Table2() { CarReg = "789CCC", Kilos = "54KG", Driver = "Driver 7", Route = 65.45, Site = "Hyderabad" }, 
      }; 

結果データを保持するのリストを作成します。

List<Table1> oneList = new List<Table1>(); 

テーブル2にない行を識別するためのループスルー

bool matchFound = false; // an indicator if match is found in table 2 

     foreach (var item in data1) 
     { 
      foreach (var item2 in data2) 
      { 
       if (item.CarReg != item2.CarReg) 
       { 
        matchFound = false; 
       } 
       else 
       { 
        matchFound = true; 
        break; 
       } 
      } 
      if (!matchFound) 
      { 
       if (!oneList.Contains(item)) 
       { 
        oneList.Add(item); 
       } 
      } 

     } 

このヘルプが必要です。

関連する問題