SQL for MSACCESS如何实现字符分隔的数据层次结构?

SQL for MSACCESS如何实现字符分隔的数据层次结构?,sql,database,ms-access,data-structures,Sql,Database,Ms Access,Data Structures,比如说,有一个扁平的顺序的层次结构表,其中有一个表示层次结构级别的特殊字符“+” hr_table ID FIELD1 My irrelevant comments ---------------- 1 ASSETS No pluses - it means level0 hierarchy 2 +ASSETS_01 Level1 hierarchy 3 ++345667654 Level2 hierarchy 4 ++56325

比如说,有一个扁平的顺序的层次结构表,其中有一个表示层次结构级别的特殊字符“+”

hr_table
ID   FIELD1        My irrelevant comments
----------------
1    ASSETS        No pluses - it means level0 hierarchy
2    +ASSETS_01    Level1 hierarchy
3    ++345667654   Level2 hierarchy
4    ++563255512   Level2 hierarchy
5    ...
有没有办法使用SQL在MSACCESS中创建字段结构?我试图将最终数据结构如下:

final_data_table
ID  LEVEL0     LEVEL1       LEVEL2    ...
-------------------------------------------
1   ASSETS     ASSETS_01    345667654
2   ASSETS     ASSETS_01    563255512

非常感谢您的帮助

好奇心征服了我,所以我探索了查询方法。我求助于使用域聚合函数。请注意,域聚合函数在处理大型数据集时可能执行缓慢。但是,请考虑:

问题1:

SELECT hr_table.ID, IIf([Field1] Like "+*",Left([Field1],InStrRev([Field1],"+")),0) AS Prefix, IIf([Field1] Like "+*",Null,[Field1]) AS Asset1, IIf(InStrRev([Field1],"+")=1,Mid([Field1],2),Null) AS Asset2, IIf([Field1] Like "++*",Mid([Field1],InStrRev([Field1],"+")+1),Null) AS Data
FROM hr_table;
问题2:

SELECT Query1.ID, Query1.Prefix, DMax("Asset1","Query1","ID<=" & [ID]) AS A1, DMax("Asset2","Query1","ID<=" & [ID]) AS A2, Query1.Data
FROM Query1
WHERE ((Not (Query1.Data) Is Null));

我绝对不确定3级及以上的治疗方法。可能VBA将是解决问题的唯一方法。

好奇心战胜了我,所以我探索了查询方法。我求助于使用域聚合函数。请注意,域聚合函数在处理大型数据集时可能执行缓慢。但是,请考虑:

问题1:

SELECT hr_table.ID, IIf([Field1] Like "+*",Left([Field1],InStrRev([Field1],"+")),0) AS Prefix, IIf([Field1] Like "+*",Null,[Field1]) AS Asset1, IIf(InStrRev([Field1],"+")=1,Mid([Field1],2),Null) AS Asset2, IIf([Field1] Like "++*",Mid([Field1],InStrRev([Field1],"+")+1),Null) AS Data
FROM hr_table;
问题2:

SELECT Query1.ID, Query1.Prefix, DMax("Asset1","Query1","ID<=" & [ID]) AS A1, DMax("Asset2","Query1","ID<=" & [ID]) AS A2, Query1.Data
FROM Query1
WHERE ((Not (Query1.Data) Is Null));

我绝对不确定3级及以上的治疗方法。可能是VBA将是唯一的解决方法。

以下代码已经过测试,并与您提到的数据结构一起工作。它目前设置为最多处理10个级别,但这很容易更改。棘手的部分是,在为该行设置所有级别之前(新行从不同的level1值开始,或者当提供了多个level-n值时),不要写出记录。最后一行在输入的eof之后写入

Option Compare Database
Option Explicit

Function Parse_Fields()
Dim dbs As DAO.Database
Dim rsIN    As DAO.recordSet
Dim rsOUT   As DAO.recordSet
Dim i       As Integer
Dim iPlus   As Integer
Dim aLevels(10)
Dim bAdding As Boolean

    Set dbs = CurrentDb
    Set rsIN = dbs.OpenRecordset("hr_table")
    Set rsOUT = dbs.OpenRecordset("final_data_table")
    bAdding = False

    Do While Not rsIN.EOF
        'Debug.Print "Input: " & rsIN!field1
        If left(rsIN!field1, 1) <> "+" Then
            ' Check if not first time thru... if not, write prior levels..
            If bAdding = True Then
                rsOUT.Update
            End If
            iPlus = 0
            rsOUT.AddNew
            rsOUT!Level0 = rsIN!field1
            bAdding = True
            ' Don't issue the .Update yet! Wait until another Level0 or EOF.
        Else
            For iPlus = 1 To 10         ' Change code if more than ten levels
                If Mid(rsIN!field1, iPlus, 1) <> "+" Then Exit For
            Next iPlus

            ' Check if same level as previous!  If so, do NOT overlay!
            If Not IsNull(rsOUT.Fields(iPlus)) Then
                For i = 1 To iPlus - 1      ' Save the proper levels for the new record.
                    aLevels(i) = rsOUT.Fields(i)
                Next i
                rsOUT.Update                ' Need to write out record.
                rsOUT.AddNew
                For i = 1 To iPlus          ' Populate the new record with prior levels
                     rsOUT.Fields(i) = aLevels(i)
                Next i
                rsOUT.Fields(iPlus) = Mid(rsIN!field1, iPlus)       ' Add the new level
            Else
                rsOUT.Fields(iPlus) = Mid(rsIN!field1, iPlus)
            End If
        End If
        rsIN.MoveNext               ' Get next input
    Loop

    ' Need to write out the final record we have beenbuilding!
    rsOUT.Update

    rsIN.Close
    rsOUT.Close
    Set rsIN = Nothing
    Set rsOUT = Nothing
    Set dbs = Nothing
    Debug.Print "FINISHED!!"

End Function
选项比较数据库
选项显式
函数Parse_Fields()
Dim数据库作为DAO.Database
将rsIN设置为DAO.recordSet
将rsOUT设置为DAO.recordSet
作为整数的Dim i
Dim iPlus作为整数
暗电平(10)
模糊标记为布尔值
设置dbs=CurrentDb
Set rsIN=dbs.OpenRecordset(“hr_表”)
Set rsOUT=dbs.OpenRecordset(“最终数据表”)
标记=假
不做rsIN.EOF
“Debug.Print”输入:&rsIN!字段1
如果左(rsIN!field1,1)“+”则
'如果不是第一次通过,请检查。。。如果没有,请填写之前的级别。。
如果bAdding=True,则
rsOUT.Update
如果结束
iPlus=0
rsOUT.AddNew
滚开!Level0=rsIN!字段1
标记=正确
'暂时不要发布.Update!等待另一个级别0或EOF。
其他的
对于IPLU=1至10’,如果超过十个级别,则更改代码
如果Mid(rsIN!field1,iPlus,1)“+”则退出
下一个iPlus
'检查是否与上一个级别相同!如果是,请不要覆盖!
如果不是IsNull(rsOUT.Fields(iPlus)),则
对于i=1到iPlus-1'保存新记录的适当级别。
aLevels(i)=rsOUT.Fields(i)
接下来我
rsOUT.Update需要写出记录。
rsOUT.AddNew
对于i=1到iPlus,用以前的级别填充新记录
rsOUT.Fields(i)=aLevels(i)
接下来我
rsOUT.Fields(iPlus)=Mid(rsIN!field1,iPlus)'添加新级别
其他的
rsOUT.Fields(iPlus)=Mid(rsIN!field1,iPlus)
如果结束
如果结束
rsIN.MoveNext“获取下一个输入
环
“需要写出我们正在建立的最终记录!
rsOUT.Update
rsIN.关闭
关上
设置rsIN=Nothing
设为零
设置dbs=Nothing
调试。打印“完成!!”
端函数

以下代码已经过测试,可以与您提到的数据结构一起使用。它目前设置为最多处理10个级别,但这很容易更改。棘手的部分是,在为该行设置所有级别之前(新行从不同的level1值开始,或者当提供了多个level-n值时),不要写出记录。最后一行在输入的eof之后写入

Option Compare Database
Option Explicit

Function Parse_Fields()
Dim dbs As DAO.Database
Dim rsIN    As DAO.recordSet
Dim rsOUT   As DAO.recordSet
Dim i       As Integer
Dim iPlus   As Integer
Dim aLevels(10)
Dim bAdding As Boolean

    Set dbs = CurrentDb
    Set rsIN = dbs.OpenRecordset("hr_table")
    Set rsOUT = dbs.OpenRecordset("final_data_table")
    bAdding = False

    Do While Not rsIN.EOF
        'Debug.Print "Input: " & rsIN!field1
        If left(rsIN!field1, 1) <> "+" Then
            ' Check if not first time thru... if not, write prior levels..
            If bAdding = True Then
                rsOUT.Update
            End If
            iPlus = 0
            rsOUT.AddNew
            rsOUT!Level0 = rsIN!field1
            bAdding = True
            ' Don't issue the .Update yet! Wait until another Level0 or EOF.
        Else
            For iPlus = 1 To 10         ' Change code if more than ten levels
                If Mid(rsIN!field1, iPlus, 1) <> "+" Then Exit For
            Next iPlus

            ' Check if same level as previous!  If so, do NOT overlay!
            If Not IsNull(rsOUT.Fields(iPlus)) Then
                For i = 1 To iPlus - 1      ' Save the proper levels for the new record.
                    aLevels(i) = rsOUT.Fields(i)
                Next i
                rsOUT.Update                ' Need to write out record.
                rsOUT.AddNew
                For i = 1 To iPlus          ' Populate the new record with prior levels
                     rsOUT.Fields(i) = aLevels(i)
                Next i
                rsOUT.Fields(iPlus) = Mid(rsIN!field1, iPlus)       ' Add the new level
            Else
                rsOUT.Fields(iPlus) = Mid(rsIN!field1, iPlus)
            End If
        End If
        rsIN.MoveNext               ' Get next input
    Loop

    ' Need to write out the final record we have beenbuilding!
    rsOUT.Update

    rsIN.Close
    rsOUT.Close
    Set rsIN = Nothing
    Set rsOUT = Nothing
    Set dbs = Nothing
    Debug.Print "FINISHED!!"

End Function
选项比较数据库
选项显式
函数Parse_Fields()
Dim数据库作为DAO.Database
将rsIN设置为DAO.recordSet
将rsOUT设置为DAO.recordSet
作为整数的Dim i
Dim iPlus作为整数
暗电平(10)
模糊标记为布尔值
设置dbs=CurrentDb
Set rsIN=dbs.OpenRecordset(“hr_表”)
Set rsOUT=dbs.OpenRecordset(“最终数据表”)
标记=假
不做rsIN.EOF
“Debug.Print”输入:&rsIN!字段1
如果左(rsIN!field1,1)“+”则
'如果不是第一次通过,请检查。。。如果没有,请填写之前的级别。。
如果bAdding=True,则
rsOUT.Update
如果结束
iPlus=0
rsOUT.AddNew
滚开!Level0=rsIN!字段1
标记=正确
'暂时不要发布.Update!等待另一个级别0或EOF。
其他的
对于IPLU=1至10’,如果超过十个级别,则更改代码
如果Mid(rsIN!field1,iPlus,1)“+”则退出
下一个iPlus
'检查是否与上一个级别相同!如果是,请不要覆盖!
如果不是IsNull(rsOUT.Fields(iPlus)),则
对于i=1到iPlus-1'保存新记录的适当级别。
aLevels(i)=rsOUT.Fields(i)
接下来我
rsOUT.Update需要写出记录。
rsOUT.AddNew
对于i=1到iPlus,用以前的级别填充新记录
rsOUT.Fields(i)=aLevels(i)
接下来我
rsOUT.Fields(iPlus)=Mid(rsIN!field1,iPlus)'添加新级别
其他的
rsOUT.Fields(iPlus)=Mid(rsIN!field1,iPlus)
如果结束
如果结束
rsIN.MoveNext“获取下一个输入
环
“需要写出我们正在建立的最终记录!
rsOUT.Update
rsIN.关闭
关上
设置rsIN=Nothing
设为零
设置dbs=Nothing
调试。打印“完成!!”
端函数
多少层