2013-06-12 20 views
0

我有兩個數據表dt1和dt2,我需要循環,並將dt1的兩列與dt2的相同兩列進行比較。我是Linq的初學者,但不確定使用Linq會更快嗎?請幫助:需要更快的解決方案,快速有效地循環兩個數據表?

每個DataTable有超過4500行和514列的數據,所以它是我們在這裏處理的一個大型數據集。

列位置「0」在兩個數據表中都有每行的唯一標識。我試圖比較列位置「6」中的數據,並將列位置「7」中的數據值從一個數據表中比較到另一個數據表中。

我的代碼在這裏需要大約10-15分鐘來處理。

什麼是最好的和更快的解決方案來比較從一個DataTable到另一個DataTable的兩列?

這裏是我的代碼

public void CompareDataTables(DataTable dt1, DataTable dt2) 
{ 

    foreach (DataRow row1 in dt1.Rows) 
     { 
      foreach (DataRow row2 in dt2.Rows) 
      { 
       var array1 = row1.ItemArray; 
       var array2 = row2.ItemArray; 

       if(row1[0].ToString() == row2[0].ToString()) 
       { 

        if (row1[6].ToString() != row2[6].ToString()) 
        { 
         tbCPDEResults.Text += "Project ID: " + row1[0] + " has a change in INV Approval Status. \nOld Value: " + row1[6] + " \nNew Value: " + row2[6] + "\n"; 
        } 


        if (row1[7].ToString() != row2[7].ToString()) 
        { 
         tbCPDEResults.Text += "Project ID: " + row1[0] + " has a change in INV Progress. \nOld Value: " + row1[7] + " \nNew Value: " + row2[7] + "\n"; 
        } 

       } 

      }//inner foreach 
      }//outter foreach 

}

回答

0

在關係數據庫管理系統,這被稱爲「嵌套循環連接」,並且它通常是效率最低的(雖然你可能不有一個選擇)。

幸運的是,它聽起來像你一樣 - 你可以改爲「合併連接」。基本上,您可以通過共享的唯一標識符對兩個表進行排序,然後一次掃描兩個表。

int rowIndex1 = 0; 
    int rowIndex2 = 0; 
    while (rowIndex1 < table1.Rows.Count && rowIndex2 < table2.Rows.Count) 
     { 
     DataRow row1 = table1.Rows[rowIndex1]; 
     DataRow row2 = table2.Rows[rowIndex2]; 

     int pk1 = Int32.Parse((string)row1[0]); 
     int pk2 = Int32.Parse((string)row2[0]); 

     if (pk1 == pk2) 
      { 
      string field1A = (string)row1[6]; 
      string field2A = (string)row2[6]; 
      if (field1A != field2A) Console.WriteLine("Field A differs for record #{0}: table 1 is {1}, tables 2 is {2}.", pk1, field1A, field2A); 

      string field1B = (string)row1[7]; 
      string field2B = (string)row2[7]; 
      if (field1B != field2B) Console.WriteLine("Field B differs for record #{0}: table 1 is {1}, tables 2 is {2}.", pk1, field1B, field2B); 

      ++rowIndex1; 
      ++rowIndex2; 
      } 
     else if (pk1 > pk2) 
      { 
      // There is no record in table 2 with this ID 
      ++rowIndex2; 
      } 
     else if (pk2 > pk1) 
      { 
      // There is no record in table 1 with this ID 
      ++rowIndex1; 
      } 
     } 

順便提一下,如果您可以將數據導入某種SQL服務器,這將變得容易得多。一個簡單的SELECT就可以做到。

+0

感謝fellas的快速反應,我測試並最終使用@Jon所有交易建議的while循環解決方案它的作用就像一個魅力!它比我的foreach解決方案更高效,更快! :)如果兩個數據源是靜態的並且總是相同的模式,我肯定會在數據庫中這樣做。不幸的是,我必須分析sqlbulkcopy進入數據庫之前的數據集,因爲新列或刪除了列。不完全是最好的情況,但它是客戶想要的,並意識到風險。 – NewCsharper

+0

pk1和pk2可能是字符串,因此它們不是順序int(1,2,3,4 ...等)。他們混合int和字符串/ varchar。有時候,一行將在表1中,但不在表2中,反之亦然。我有其他代碼來檢查新的或刪除的行,但我將如何修改上述答案來處理刪除或插入的行,其中pk是一個字符串? – NewCsharper

+0

混合整數和字符串?伊克。那麼,上面的代碼也可以用於字符串,只需更改pk字段的類型並放棄解析。只要確保表格與您使用的比較運算符的排序規則相同即可。如果您想記錄一個表格中存在的記錄,但不記錄其他記錄,則可以將其添加到註釋顯示的位置。 – 2013-06-13 15:36:26

0

個人而言,我討厭的數據表,這是對DB-級別運行單獨的查詢最好的做法,無論如何,如果你堅持的數據表解決的問題在應用程序本身,這是更optimalized:

public static void CompareDataTables(DataTable dt1, DataTable dt2) { 
    var builder = new StringBuilder(10000); 

    var rows = new Dictionary<string, List<DataRow>>(dt1.Rows.Count * 3); 
    foreach (DataRow row in dt1.Rows) { 
     string key = row[0].ToString(); 
     List<DataRow> rowSet; 
     if (!rows.TryGetValue(key, out rowSet)) { 
     rowSet = new List<DataRow> { row }; 
     rows.Add(key, rowSet); 
     } else { 
     rowSet.Add(row); 
     } 
    } 

    foreach (DataRow row2 in dt2.Rows) { 
     List<DataRow> rowSet; 
     if (rows.TryGetValue(row2[0].ToString(), out rowSet)) { 
     foreach (var row1 in rowSet) { 
      if (row1[6].ToString() != row2[6].ToString()) { 
      builder.AppendFormat("Project ID: {0} has a change in INV Approval Status. \nOld Value: {1} \nNew Value: {2}\n", row1[0], row1[6], row2[6]); 
      } 
      if (row1[7].ToString() != row2[7].ToString()) { 
      builder.AppendFormat("Project ID: {0} has a change in INV Progress. \nOld Value: {1} \nNew Value: {2}\n", row1[0], row1[7], row2[7]); 
      } 
     } 
     } 
    } 
    tbCPDEResults.Text = builder.ToString(); 
    } 
+0

不錯,你給出了一個「散列連接」的例子,所以在我們三人之間我們已經列出了連接表最常用的方法。現在我們只需要有人演示一下位圖連接。 – 2013-06-12 15:44:34

+0

謝謝@Ondrej Svejdar – NewCsharper