在VB中合并两个数据表(相同模式)并仅获取不匹配的行

时间:2012-11-07 21:05:28

标签: vb.net

我有两个数据表。我想合并它们,并希望从两个数据表中只获取不匹配的行。有人可以帮忙吗?

目前我正在使用以下代码,但它什么都没有返回:

Actual_Table = myDataSet_Actual.Tables("Actuals")
Planned_Table = myDataset_Planned.Tables("Planned")

Planned_Table.AcceptChanges()
Planned_Table.Merge(Actual_Table, False)

change = Planned_Table.GetChanges(DataRowState.Added)
DGV1.DataSource = change ' DGV1= Data grid view

2 个答案:

答案 0 :(得分:0)

我希望这可以帮到你:http://www.dotnetperls.com/datatable-compare-rows

在示例中,它将比较结果写入控制台,但我猜你可以做出魔术;)

祝你好运!

编辑:实际上,如果您的DataTable具有相同的行数并且您要将这些行进行一对一比较,那么您应该更改一个For Each语句For声明。类似的东西:

For i As Integer = 0 To RowNo - 1
    'compare datatable1_row(i) with datatable2_row(i) and do the magic
Next

答案 1 :(得分:0)

TL; DR

您可以使用以下代码执行此操作,但请继续阅读以获取更多详细信息:

change = Planned_Table.AsEnumerable _
                      .Except(Actual_Table.AsEnumerable, DataRowComparer.Default) _ 
                      .CopyToDataTable

这里有几点需要注意:

正如此question中指出的那样,DataTable.Merge不会更改行状态,因此查找DataRowState.Added行始终为空。

此外,Merge将第二个表中的每一行添加到第一个表中,因此即使RowState 具有,第二个表中的所有也会出现改变。

最后,假设我们只将第二个数据表中的唯一值添加到第一个数据表中,我们只返回第二个集合中的元素,而不是第一个集合中的元素。也许这就是你想要的,但是如果你真的想要其中任何一个,我会描述这两个选项。

我们需要的工具

如其他SO问题herehere中所示,我们可以使用LINQ Set Operations中的任何一个找到正确的条目集:

您可以在MSDN中进一步探索这些内容,但正如this中提到的那样,UnionConcat中的DataRowIEqualityComparer都可以将枚举附加到另一个上,但是Union将删除重复项(在检查DataRowComparer.Default的相等性时,您必须传入重载的DataTableExtensions = Dim dt, dataTable1, dataTable2 As New DataTable With dt.Columns .Add("ID", GetType(Integer)) .Add("Name", GetType(String)) End With dataTable1 = dt.Clone dataTable2 = dt.Clone With dataTable1.Rows .Add(1, "Tod") .Add(2, "Jim") End With With dataTable2.Rows .Add(2, "Jim") .Add(3, "Han") End With

另外,我们要枚举DataTable,为此,我们需要从Right Outer Join命名空间调用AsEnumerable方法。

解决方案设置

我们正在查看相同的代码,这里有一些我们可以执行设置操作的基本DataTable

Full Outer Join

解决方案集

因此,如果您只希望第二个表中的新项目没有出现在第一个表格中,那么您需要一个Inner Join

Right Outer Join

如果您希望两组之间的所有数据不同,则需要Except排除Datatable

Right Outer Join

您可以在此Jeff Atwood post中详细了解不同的集合以及创建它们的联接。

代码

如果你想要第一个选项,你可以通过在第二个Dim just2 As DataTable just2 = dataTable2.AsEnumerable _ .Except(dataTable1.AsEnumerable, DataRowComparer.Default) _ .CopyToDataTable() 上调用| ID | Name | | 3 | Han | 并传入第一个

来获取元素和仅在第二个集合中
DataRowComparer

输出将是:

Union

如果您想要每组中的唯一值,则必须调用distinct两次,然后将这两个值连接起来。我们不需要将Dim just1 As IEnumerable(Of DataRow) Dim just2 As IEnumerable(Of DataRow) Dim union As DataTable 'get rows that are only in table1 just1 = dataTable1.AsEnumerable.Except(dataTable2.AsEnumerable, DataRowComparer.Default) 'get rows that are only in table2 just2 = dataTable2.AsEnumerable.Except(dataTable1.AsEnumerable, DataRowComparer.Default) 'get all unique rows union = just1.Union(just2).CopyToDataTable 传递给CopyToDataTable方法,因为我们保证两个表中没有重复项

IEnumerable(Of DataRow)

由于我们不需要单独使用唯一元素集,因此无需致电AsEnumerable,因此我们可以使用| ID | Name | | 1 | Tod | | 3 | Han |

重新投入{{1}}

联合的输出将是:

{{1}}