4

リンクされたリストによってグループ化された要素があるいくつかのテーブルを受け取りましたが、それを処理するのに苦労しています。

関数はそのままで機能しますが、タスク スケジューラ以降に起動したときにマクロがどこにあるのか、またはメモリの問題があるのか​​ とよく尋ねられます。

次のコードを使用して idGroup (英語に翻訳) を見つけます。30 000 行と約 2500 グループで最大 1 時間かかるため、特に速度を改善する方法があるかどうか疑問に思っています... (そのため、進行状況を確認するために 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
4

1 に答える 1

2

いくつかの提案:

  1. 多数のレコードセットを開いています ( への呼び出しごとにprecedentUid)。idGroup代わりに、 +で並べ替えられた単一のレコードセットを使用しid1、適切な値を上または下にシークすることを検討してください。
  2. idGroup+で常に検索しているのでid1、これを主キーにすることをお勧めします。その後、この方法を使用してSeek検索を高速化できます。
  3. 主キーを取得すると、単一のレコードセットを編集可能にする必要がなくなり、読み込みが速くなります。を更新する必要がある場合はidGroup、SQL ステートメントを と共に使用しますCurrentDb.Execute
  4. の検索結果をキャッシュしますidGroup( Dictionary[ツール] -> [参照] のMicrosoft Scripting Runtime参照)。そうすれば、再帰中に検索を繰り返さなくなります。
  5. サンプル データはすべて数値のように見えますが、レコードセットから文字列として取得しています。基になるデータ型は であるべきでありLong、 ではありませんText。これを制御できない場合は、適切なデータ型で一時テーブルを作成することを検討します。
于 2012-10-28T15:53:10.203 に答える