获取递归查询以在Access 2013中工作

时间:2016-07-06 21:01:11

标签: sql-server vba recursion access-vba

经过一天的研究,我以为我的问题就在最后。我让自己全都学习了递归查询,并设法让它在SQL Server Management Studio 2014中执行得非常漂亮。但是,在将我在SQL Server 2014中编写的查询转换为Access 2013应用程序时,我立即被击落。阅读其他文章,我现在明白Access不支持递归查询。有了这个,我需要帮助找到一种资源有效的方法来提取这些记录并将它们放入数组变量中。我过去在VBA中模仿这一点的努力是可怕的;导致处理30-60秒。任何有关如何利用这一过程的建议将不胜感激。

我想模仿的递归查询是:

WITH MyCTE(BusinessUnitID, Active)
AS(

SELECT a.BusinessUnitID, a.Active
FROM t_EMS_BM_BusinessUnits AS a
WHERE BusinessUnitID = 7

UNION ALL

SELECT d.BusinessUnitID, d.Active
FROM MyCTE AS c
INNER JOIN t_EMS_BM_BusinessUnits AS d
ON c.BusinessUnitID = d.ParentUnit)

SELECT *
FROM MyCTE
WHERE Active = 1

我糟糕的VBA脚本是:

Private Sub LoadArray(intBU As Integer)
    'set rollup data for business unit by adding all child units to intBUs array
    Dim sql As String
    Dim rs As Recordset
    Dim intCount As Integer

    sql = "SELECT BusinessUnitID, ParentUnit FROM t_EMS_BM_BusinessUnits WHERE Active = true ORDER BY BusinessUnitID"
    Set rs = currentdb.OpenRecordset(sql, dbOpenDynaset, dbSeeChanges)

    'look for child units
    With rs

        intCount = 0
        ReDim intBUs(1 To 1) As Integer

        If Not .EOF And Not .BOF Then
            .MoveLast
            .MoveFirst

            Do While Not .EOF

                If IsChild(intBU, !BusinessUnitID) = True Then
                    'add to array
                    intCount = intCount + 1

                    If intCount > 1 Then
                        ReDim Preserve intBUs(1 To UBound(intBUs) + 1) As Integer
                        intBUs(UBound(intBUs)) = !BusinessUnitID
                    ElseIf intCount = 1 Then
                        intBUs(UBound(intBUs)) = !BusinessUnitID
                    End If

                End If

                .MoveNext
            Loop
        End If
        .Close
    End With

    Set rs = Nothing

Private Function IsChild(TargetBU, CurrentBU As Integer) As Boolean
    'check if unit is lowest level child
    'is TargetBU a child of CurrentBU?

    Dim intX As Integer
    Dim intCount As Integer

    intX = 0

    If TargetBU = CurrentBU Then
        'return a value of true
        IsChild = True
    Else

        Do Until intX = -1
            'find bottom level of heiarchy

            intCount = DCount("BusinessUnitID", "t_EMS_BM_BusinessUnits", "ParentUnit=" & CurrentBU)
            If intCount = 0 Then
                intX = -1
            Else
                CurrentBU = DLookup("BusinessUnitID", "t_EMS_BM_BusinessUnits", "ParentUnit=" & CurrentBU)
                intX = 0
            End If
        Loop

        'reset sentinal value
        intX = 0

        Do Until intX = -1
            'tree up until the record matches the TargetBU or reaches the top "0"
            If CurrentBU = TargetBU Or CurrentBU = 0 Then
                IsChild = True
                intX = -1
            Else
                'move up to the next level
                CurrentBU = Nz(DLookup("ParentUnit", "t_EMS_BM_BusinessUnits", "BusinessUnitID = " & CurrentBU), 0)
                IsChild = False
                intX = 0
            End If
        Loop

    End If
End Function

0 个答案:

没有答案