2017-11-10 125 views
1

說,有一個扁平順序層表以特殊字符「+」表示層級SQL for MSACCESS如何實現字符分隔的數據層次結構?

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

可以有多少層次,並且總會有最多層次的行(即如果3層,總會有3行來填充你的表)?我知道你可以使用VBA在Access中處理,並且可以使用Excel重新格式化爲扁平行。 –

+0

什麼標準決定那些Level2數字與ASSETS_01而不是ASSETS_02? – June7

+0

需要檢查FIELD1成員以計算MAX出現的「+」。這將決定最高級別數量。但這是非常預先確定的。假設最高級別數爲5(作爲例子),它不會改變。 –

回答

0

好奇心越來越好,所以我探索了查詢方法。我訴諸於使用域聚合函數。請注意,對於大型數據集,域聚合函數可以緩慢執行。然而,考慮:

查詢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; 

QUERY2:

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)); 

QUERY3:

SELECT Query2.Prefix, Query2.A1, Query2.A2, Query2.Data, DCount("*","Query2","A1='" & [A1] & "' AND A2='" & [A2] & "' AND Prefix = '" & [Prefix] & "' AND ID<=" & [ID]) AS GrpSeq 
FROM Query2; 

Query4:

TRANSFORM Max(Query3.Data) AS MaxOfData 
SELECT Query3.A1, Query3.A2, Query3.GrpSeq 
FROM Query3 
GROUP BY Query3.A1, Query3.A2, Query3.GrpSeq 
PIVOT Query3.Prefix; 

我絕對不確定Level3及以後的治療方法。可能是VBA將只能解決的方法。

0

以下代碼已經過測試,並與您提到的數據結構一起工作。目前它最多可以處理10個級別,但可以輕鬆更改。棘手的部分是不寫出的記錄,直到你有該行的所有級別(新行開始不同的level1值,或提供多個level-n值)。最後一行是在輸入之後編寫的。

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