我收到一些表,其中有按链表分组的元素,我很难处理它.
该函数可以找到它,但我常常被问到从任务调度程序启动时它的宏在哪里或有一些内存问题.
我使用下面的代码找出idGroup(翻译成英文),我想知道是否有办法改进它,特别是它的速度,因为它需要长达一个小时的30 000行和大约2500组…(这就是我用VBA看进展的原因……)
'Simple example
'idGroup,id2,id1
'6338546,14322882,13608969
'6338546,13608969,13255363
'6338546,6338546,14322882
'6338546,11837926,11316332
'6338546,12297571,11837926
'6338546,13255363,12811071
'6338546,12811071,12297571
'6338546,7610194,7343817
'6338546,7935943,7610194
'6338546,8531387,7935943
'6338546,6944491,6611041
'6338546,7343817,6944491
'6338546,9968746,9632204
'6338546,10381694,9968746
'6338546,6611041,0
'6338546,8920224,8531387
'6338546,9632204,8920224
'6338546,11316332,10941093
'6338546,10941093,10381694
Public Function GetidGroup()
'first id1 is always 0
sql = "SELECT idGroup, id2, id1 FROM TABLE_WITH_LINKED_LIST WHERE id1='0' ORDER BY id2 DESC"
Dim rs As Recordset
Dim uidLikedList As String, id2 As String, id1 As String
Set rs = CurrentDb.OpenRecordset(sql)
Dim total As Long
Dim idGroup As String
Dim incrément As Long, progress As Double
total = rs.RecordCount
incrément = 1
While Not rs.EOF
progress = Math.Round(100 * incrément / total, 2)
'Print in order to avoir freezing
Debug.Print progress
If rs.Fields("idGroup") = "" Then
id2 = rs.Fields("id2")
idGroup = precedentUid(id2)
rs.Edit
rs.Fields("idGroup") = idGroup
rs.Update
End If
incrément = incrément + 1
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
GetidGroup = total
End Function
'Recursive function
'Deepest so far is about 62 calls
Public Function precedentUid(id2 As String) As String
sql = "SELECT idGroup, id2 FROM TABLE_WITH_LINKED_LIST WHERE id1 = '" & id2 & "'"
Dim rs As Recordset
Dim precedentid2 As String
Dim idGroup As String
Dim ret As String
Set rs = CurrentDb.OpenRecordset(sql)
If rs.EOF Then
rs.Close
Set rs = Nothing
precedentUid = id2
Else
'Some records have several references
'56 impacted records :
'TODO : Give the min id2 to the group
ret = "-1"
While Not rs.EOF
If rs.Fields("idGroup") = "" Then
precedentid2 = rs.Fields("id2")
idGroup = precedentUid(precedentid2)
If ret = "-1" Or CLng(ret) > CLng(idGroup) Then
ret = idGroup
End If
'Debug.Print id2 & " " & precedentid2 & " " & idGroup
rs.Edit
rs.Fields("idGroup") = idGroup
rs.Update
End If
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
precedentUid = ret
End If
End Function
最佳答案 一些建议:
>您正在打开大量记录集(对于precedentUid的每次调用).相反,请考虑使用按idGroup id1排序的单个记录集,并向上或向下搜索适当的值.
>由于您总是在idGroup id1上搜索,我建议将其作为主键.然后,您将能够使用Seek方法进行更快速的搜索.
>一旦拥有主键,就不需要编辑单个记录集,并且加载速度更快.必须更新idGroup时,请将SQL语句与CurrentDb.Execute一起使用.
>在字典中缓存搜索idGroup的结果(参考Microsoft Scripting Runtime in Tools – > References).这样,您不会在递归时重复搜索.
>您的示例数据似乎是所有数字,但您从记录集中将它们作为字符串进行检索.基础数据类型应为Long,而不是Text.如果您无法控制此情况,我会考虑使用适当的数据类型创建临时表.