5

我正在努力解决排序问题。

我有一张如下表:

aspect_id (int)
aspect_text (memo)
root_id (int) which has as a foreign key a aspect_id

我有一个带有以下虚拟数据的非循环树:

aspect_id  aspect_text  root_id 

1          root         null
2          aspect1      1
3          aspect2      1
4          aspect3      2
5          aspect5      4

在示例中,数据已正确排序,而在我的数据库中则没有。我想排序它从根元素开始,然后找到一个孩子,输出那个孩子并递归地做。

使用 CTE 是相当可行的。Access 不支持此功能。使用 CTE,它将类似于:

WITH aspectTree (aspect_id, root_id, Level#) AS 
(
        Select 
            aspect.aspect_id, 
            aspect.root_id,
            0
        FROM aspect
        WHERE aspect.aspect_id = 44
    UNION ALL
        SELECT 
            aspect.aspect_id, 
            aspect.root_id, 
            T.Level# + 1
        FROM aspect
        INNER JOIN aspectTree AS T 
            On T.aspect_id = aspect.root_id
)
SELECT * FROM aspectTree;
4

3 回答 3

1

如果不考虑性能,这个相当简单的解决方案将起作用:

Public Function GetLevel(ByVal lngNodeId As Long) As Long

    Dim varRootId As Variant

    varRootId = DLookup("root_id", "aspect", "aspect_id=" & lngNodeId)

    If IsNull(varRootId) Then
        GetLevel = 0
    Else
        GetLevel = GetLevel(varRootId) + 1
    End If

End Function

然后,您可以在 ORDER BY 子句中使用该函数:

SELECT aspect.*
FROM aspect
ORDER BY GetLevel([aspect_id]), aspect_text
于 2010-12-20T19:24:05.387 回答
0

我不知道以下内容是否适合您,但您可以使用物料清单算法。

于 2009-08-05T19:38:31.043 回答
0

它充满了测试代码,但我做了一些在 vb 代码中有效的事情。它真的很丑而且很慢,但它确实有效。我现在正在清理它,刚刚开始工作。解决方案是递归函数。如果发现该节点有子节点,该函数会调用自身。它似乎覆盖了数组,这就是为什么它是一个数组数组。代码很可怕,但它可以工作,这就是我所需要的。数据库现在并且将保持很小(<1000 条记录),因此速度不是问题。感谢您的评论和回答,如果有人知道我更好的解决方案,我很想听听。

私有函数 Fillarray(值作为整数)
Dim done As Boolean

j = j + 1
esql = "从 root_id = " & value 的方面选择 aspect_id
设置 rec(j) = db.OpenRecordset(esql)
将 k 调暗为整数
k = j
不做时做rec(k).EOF
完成=真
arra(i) = rec(k).Fields(0)
将 temp1 调暗为字符串
temp1 = DLookup("[aspects]", "[aspect]", "[aspect_id] = " & rec(k).Fields(0))
db.Execute "INSERT INTO sortedaspect (aspect_id, aspect) VALUES (" & rec(k).Fields(0) & ", '" & temp1 & "')"

        esql = "从 root_id = " & rec(k).Fields(0) 的方面选择 aspect_id

        设置 rec(90) = db.OpenRecordset(esql)
        Do While Not rec(90).EOF 并完成
            '修复这个没有循环,你只需要知道它是否有孩子......
            Fillarray (rec(k).Fields(0))
            完成 = 假

        环形
      '下一个孩子

rec(k).MoveNext
'值 = arra(i)
我 = 我 + 1
'MsgBox arra(i - 1)
环形

结束功能
于 2009-08-07T11:39:18.333 回答