连接两个具有公共字段的数据表
Join two data tables having common fields
我有 2 个 datatable
objects (dt1
,dt2
),它们有一个共同的字段,叫做 "File_Name"。我想创建一个 datatable
(dtFinal
),结合两个数据表以用于 asp.net
的 gridview
每个表 (dt1
,dt2
) 都可以有重叠的列 header 名称,这意味着如果 dt1 有一个 header 作为 "plant_code" dt2
也可以将 header 作为 "plant_Code" 但不是强制性的。
我的 objective 将拥有一个公共数据表 (dtFinal
),其中包含来自所有单独数据表的所有 header。
我试过这样的东西
Dt1.PrimaryKey = New DataColumn() {Dt1.Columns(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "GRN" & ".csv")}
Dt2.PrimaryKey = New DataColumn() {Dt1.Columns(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "Payment Data" & ".csv")}
Dt1 = CsvToDataTable(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "GRN" & ".csv")
Dt2 = CsvToDataTable(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "Payment Data" & ".csv")
ds.Tables.Add(Dt1)
ds.Tables.Add(Dt2)
Dim drel As New DataRelation("EquiJoin", Dt2.Columns("File_Name"), Dt1.Columns("File_Name"))
ds.Relations.Add(drel)
Dim jt As New DataTable("Joinedtable")
ds.Tables.Add(jt)
For Each dr As DataRow In ds.Tables("Table1").Rows
Dim parent As DataRow = dr.GetParentRow("EquiJoin")
Dim current As DataRow = jt.NewRow()
' Just add all the columns' data in "dr" to the New table.
For i As Integer = 0 To ds.Tables("Table1").Columns.Count - 1
current(i) = dr(i)
Next
' Add the column that is not present in the child, which is present in the parent.
current("Dname") = parent("Dname")
jt.Rows.Add(current)
Next
DtFinal = ds.Tables("Joinedtable")
正在创建一个 dataset
以及 dt1 和 dt2 之间的关系...但这似乎不起作用并且在第 1 行 instance of object to be declared using New
中给我一个错误。
有人在 Vb 中尝试过类似的东西吗?或者可以编辑我的代码以使其工作。
更多信息:每个数据表 tb1 和 tb2 在第一列的 File_Name 列中都有唯一值。因此可以选择为主键。
您可以尝试数据表合并。
dt3 = new DataTable();
dt3 .Merge(dtOne);
dt3 .Merge(dtTwo);
查看此 post 了解更多 info/solutions。 Merge 2 DataTables and store in a new one
当您说 "Merge" 时,它可能意味着一件事或另一件事。比如我可能会想到这个方法
这是工作代码:
Public Sub MergeTables()
Dim t1 As New DataTable("T1")
t1.Columns.Add("C1", GetType(String))
t1.Columns.Add("C2", GetType(String))
t1.Columns.Add("C3", GetType(String))
Dim t2 As New DataTable("T2")
t2.Columns.Add("C1", GetType(String)) 'same column
t2.Columns.Add("C2", GetType(Integer)) ' same column, different data type
t2.Columns.Add("C4", GetType(String)) ' different column
Dim map As New Dictionary(Of String, String)
Dim t3 As New DataTable("T4")
MergeColumns(t3, t1, map)
MergeColumns(t3, t2, map)
Debug.WriteLine("Should be 5 columns and reality is: " & t3.Columns.Count)
' Add some data
t1.Rows.Add({"data from t1 c1", "data from t1 c2", "data from t1 c3"})
t2.Rows.Add({"data from t2 c1", 55, "data from t2 c3"})
MergeRows(t3, t1, map)
MergeRows(t3, t2, map)
t3.AcceptChanges()
For Each row As DataRow In t3.Rows
Debug.WriteLine(String.Join(";", row.ItemArray.Select(Function(o) o.ToString()).ToArray()))
Next
End Sub
Private Sub MergeColumns(totbl As DataTable, fromtbl As DataTable, map As Dictionary(Of String, String))
For Each c As DataColumn In fromtbl.Columns
If Not totbl.Columns.Contains(c.ColumnName) Then
totbl.Columns.Add(c.ColumnName, c.DataType)
map.Add(c.Table.TableName & "_" & c.ColumnName, c.ColumnName)
ElseIf Not totbl.Columns(c.ColumnName).DataType.Equals(c.DataType) Then
totbl.Columns.Add(c.Table.TableName & "_" & c.ColumnName, c.DataType)
map.Add(c.Table.TableName & "_" & c.ColumnName, c.Table.TableName & "_" & c.ColumnName)
Else
map.Add(c.Table.TableName & "_" & c.ColumnName, c.ColumnName)
End If
Next
End Sub
Private Sub MergeRows(totbl As DataTable, fromtbl As DataTable, map As Dictionary(Of String, String))
For Each row As DataRow In fromtbl.Rows
Dim newRow As DataRow = totbl.NewRow()
For Each c As DataColumn In fromtbl.Columns
newRow(map(fromtbl.TableName & "_" & c.ColumnName)) = row(c.ColumnName)
Next
totbl.Rows.Add (newRow)
Next
End Sub
结果:
data from t1 c1 ; data from t1 c2 ; data from t1 c3 ; ;
data from t2 c1 ; ; ; 55 ; data from t2 c3
但也许,您还需要其他东西。然而,这是如何做这样的事情的好例子
我有 2 个 datatable
objects (dt1
,dt2
),它们有一个共同的字段,叫做 "File_Name"。我想创建一个 datatable
(dtFinal
),结合两个数据表以用于 asp.net
每个表 (dt1
,dt2
) 都可以有重叠的列 header 名称,这意味着如果 dt1 有一个 header 作为 "plant_code" dt2
也可以将 header 作为 "plant_Code" 但不是强制性的。
我的 objective 将拥有一个公共数据表 (dtFinal
),其中包含来自所有单独数据表的所有 header。
我试过这样的东西
Dt1.PrimaryKey = New DataColumn() {Dt1.Columns(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "GRN" & ".csv")}
Dt2.PrimaryKey = New DataColumn() {Dt1.Columns(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "Payment Data" & ".csv")}
Dt1 = CsvToDataTable(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "GRN" & ".csv")
Dt2 = CsvToDataTable(System.AppDomain.CurrentDomain.BaseDirectory & "\resources\files\" & "Payment Data" & ".csv")
ds.Tables.Add(Dt1)
ds.Tables.Add(Dt2)
Dim drel As New DataRelation("EquiJoin", Dt2.Columns("File_Name"), Dt1.Columns("File_Name"))
ds.Relations.Add(drel)
Dim jt As New DataTable("Joinedtable")
ds.Tables.Add(jt)
For Each dr As DataRow In ds.Tables("Table1").Rows
Dim parent As DataRow = dr.GetParentRow("EquiJoin")
Dim current As DataRow = jt.NewRow()
' Just add all the columns' data in "dr" to the New table.
For i As Integer = 0 To ds.Tables("Table1").Columns.Count - 1
current(i) = dr(i)
Next
' Add the column that is not present in the child, which is present in the parent.
current("Dname") = parent("Dname")
jt.Rows.Add(current)
Next
DtFinal = ds.Tables("Joinedtable")
正在创建一个 dataset
以及 dt1 和 dt2 之间的关系...但这似乎不起作用并且在第 1 行 instance of object to be declared using New
中给我一个错误。
有人在 Vb 中尝试过类似的东西吗?或者可以编辑我的代码以使其工作。
更多信息:每个数据表 tb1 和 tb2 在第一列的 File_Name 列中都有唯一值。因此可以选择为主键。
您可以尝试数据表合并。
dt3 = new DataTable();
dt3 .Merge(dtOne);
dt3 .Merge(dtTwo);
查看此 post 了解更多 info/solutions。 Merge 2 DataTables and store in a new one
当您说 "Merge" 时,它可能意味着一件事或另一件事。比如我可能会想到这个方法
这是工作代码:
Public Sub MergeTables()
Dim t1 As New DataTable("T1")
t1.Columns.Add("C1", GetType(String))
t1.Columns.Add("C2", GetType(String))
t1.Columns.Add("C3", GetType(String))
Dim t2 As New DataTable("T2")
t2.Columns.Add("C1", GetType(String)) 'same column
t2.Columns.Add("C2", GetType(Integer)) ' same column, different data type
t2.Columns.Add("C4", GetType(String)) ' different column
Dim map As New Dictionary(Of String, String)
Dim t3 As New DataTable("T4")
MergeColumns(t3, t1, map)
MergeColumns(t3, t2, map)
Debug.WriteLine("Should be 5 columns and reality is: " & t3.Columns.Count)
' Add some data
t1.Rows.Add({"data from t1 c1", "data from t1 c2", "data from t1 c3"})
t2.Rows.Add({"data from t2 c1", 55, "data from t2 c3"})
MergeRows(t3, t1, map)
MergeRows(t3, t2, map)
t3.AcceptChanges()
For Each row As DataRow In t3.Rows
Debug.WriteLine(String.Join(";", row.ItemArray.Select(Function(o) o.ToString()).ToArray()))
Next
End Sub
Private Sub MergeColumns(totbl As DataTable, fromtbl As DataTable, map As Dictionary(Of String, String))
For Each c As DataColumn In fromtbl.Columns
If Not totbl.Columns.Contains(c.ColumnName) Then
totbl.Columns.Add(c.ColumnName, c.DataType)
map.Add(c.Table.TableName & "_" & c.ColumnName, c.ColumnName)
ElseIf Not totbl.Columns(c.ColumnName).DataType.Equals(c.DataType) Then
totbl.Columns.Add(c.Table.TableName & "_" & c.ColumnName, c.DataType)
map.Add(c.Table.TableName & "_" & c.ColumnName, c.Table.TableName & "_" & c.ColumnName)
Else
map.Add(c.Table.TableName & "_" & c.ColumnName, c.ColumnName)
End If
Next
End Sub
Private Sub MergeRows(totbl As DataTable, fromtbl As DataTable, map As Dictionary(Of String, String))
For Each row As DataRow In fromtbl.Rows
Dim newRow As DataRow = totbl.NewRow()
For Each c As DataColumn In fromtbl.Columns
newRow(map(fromtbl.TableName & "_" & c.ColumnName)) = row(c.ColumnName)
Next
totbl.Rows.Add (newRow)
Next
End Sub
结果:
data from t1 c1 ; data from t1 c2 ; data from t1 c3 ; ;
data from t2 c1 ; ; ; 55 ; data from t2 c3
但也许,您还需要其他东西。然而,这是如何做这样的事情的好例子