【问题标题】:MS ACCESS - Hierarchical tree sortMS ACCESS - 分层树排序
【发布时间】:2009-08-05 12:57:06
【问题描述】:

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

我有一张如下表:

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;

【问题讨论】:

  • 首字母缩略词 CTE 是什么意思?
  • CTE = 公用表表达式,是 SQL-99 标准的一部分,并被引入 SQL Server 2005。请参阅 MSDN“使用公用表表达式”(msdn.microsoft.com/en-us/library/ms190766.aspx)。
  • 您使用的是哪个版本的 Access? Access 2010 有一个新的字段类型来处理分层数据。

标签: ms-access sorting treeview tree parent-child


【解决方案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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 'Joe Celko' 不起作用,因为这里的 OP 使用的是邻接列表模型而不是嵌套集模型......除非他们完全修改他们的模式,但可能值得考虑;)
    【解决方案3】:

    它充满了测试代码,但我做了一些在 vb 代码中有效的事情。它真的很丑而且很慢,但它确实有效。我现在正在清理它,刚刚开始工作。解决方案是递归函数。如果发现该节点有子节点,该函数会调用自身。它似乎覆盖了数组,这就是为什么它是一个数组数组。代码很可怕,但它可以工作,这就是我所需要的。数据库现在并且将保持很小(

    私有函数 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) 环形 结束功能

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-31
      相关资源
      最近更新 更多