以前做项目时,常碰到需要将datatable进行分组,网上查了很多资料,有用Linq的,有用Compute方法的 这些方法我都一一尝试过
linq的性能最高,功能最强,但也是用的最头疼最麻烦的,主要是不能动态传参,需要针对每个表写一段linq代码。
compute方法最简单,但性能最差,数据量一大,比蜗牛还慢
最近做一个项目,需要实现类似EXCEL表格中的数据透视表功能以及自动筛选功能, 因为数据不一定是数据库里的数据,有可能是从EXCEL表格中导过来的,所以只能是在内存中进行数据的分姐,而且要求分组性能要高,还要能实现动态分组,也就是在源数据表不固定的情况下,可以调用同一种方法返回分组后的数据。
这样一来,以前的那些方法都不能采用,于是又跑到网上找啊找,几年过去了,关于datatable分组这一块还是没有什么新的好方法出来,不得已,只能自已琢磨了。
经过几个晚上的努力,终于做了一个函数出来,性能不错,不比在SQL语句分组查询慢多少,在这里和大家分享一下。以下是用vb.net写的代码,这个函数还可以扩展,如何扩展,看大家的了,这里只是提供一个思路
Public Function GroupToNewTable(ByVal SourceTable As DataTable, ByVal GroupField As String, ByVal sumField As String) As DataTable
Dim tb As New DataTable
Dim col As New DataColumn
Dim fields() As String
Dim field As String
fields = Split(GroupField, ",")
'创建表
For Each field In fields
col = New DataColumn
col.ColumnName = field
col.DataType = SourceTable.Columns(field).DataType
tb.Columns.Add(col)
Next
fields = Split(sumField, ",")
For Each field In fields
col = New DataColumn
col.ColumnName = field
col.DataType = SourceTable.Columns(field).DataType
tb.Columns.Add(col)
Next
Dim dv As DataView
Dim dr As DataRow
Dim dvRow As DataRowView
Dim i As Integer
Dim bCurRow As Boolean = False
dv = SourceTable.AsDataView
dv.Sort = GroupField
For Each dvRow In dv
bCurRow = True '判断是否为当前行
For Each field In Split(GroupField, ",")
If tb.Rows.Count = 0 Then
bCurRow = False
Else
If dvRow(field) = tb.Rows(tb.Rows.Count - 1)(field) Then
bCurRow = bCurRow And True
Else
bCurRow = bCurRow And False
Exit For
End If
End If
Next
If bCurRow = False Then
dr = tb.NewRow
For Each field In Split(GroupField, ",")
dr(field) = dvRow(field)
Next
For Each field In Split(sumField, ",")
dr(field) = dvRow(field)
Next
tb.Rows.Add(dr)
Else
For Each field In Split(sumField, ",")
dr(field) = isNull(dr(field), 0) + isNull(dvRow(field), 0)
Next
End If
Next
Return tb
End Function
调用方法:
dim tb as datatable
tb =GroupToNewTable(xtb, "字段1,字段2,字段3", "求和字段1,求和字段2")