我有一個job
表是否可以在Access中創建遞歸查詢?
Id
ParentID
jobName
jobStatus
根PARENTID爲0
是否有可能在Access中創建一個查詢,以找到一個給定job
根? 數據庫是沒有鏈接表的MDB。 Access版本是2003年。一個job
可以是深層次的幾個級別的大孩子。
我有一個job
表是否可以在Access中創建遞歸查詢?
Id
ParentID
jobName
jobStatus
根PARENTID爲0
是否有可能在Access中創建一個查詢,以找到一個給定job
根? 數據庫是沒有鏈接表的MDB。 Access版本是2003年。一個job
可以是深層次的幾個級別的大孩子。
不,它不是。在SServer 2005之後的SQL Server中支持遞歸查詢,但在Access中不支持。
如果你事先知道槓桿的數量,你可以寫一個qry,但它不會是一個遞歸的。
在SQL Server中,CTE(一個SQL擴展)用於那些:看http://blog.crowe.co.nz/archive/2007/09/06/Microsoft-SQL-Server-2005---CTE-Example-of-a-simple.aspx
常規的SQL但沒有遞歸性支持。
@onedaywhen:是否/應該「ISO/ANSI標準SQL」具有後綴年,以幫助將其與「ISO/ANSI標準SQL-99」區分開來? – 2015-04-08 17:30:31
你不能遞歸查詢。
您可以執行一些任意數量的左連接,但只能加入與連接數量相同的級別。
或者您可以使用Celko's "Nested Set Model"檢索所有父母。這將需要修改您的表結構,以便使插入和更新變得更加複雜。
你不能遞歸查詢。 - >無法訪問03反正,在許多其他查詢語言中,您可以 – Peter 2009-04-18 08:54:30
是的,「您」使用Access的OP的用戶不能遞歸查詢。 – tpdi 2009-04-18 21:14:40
雖然嵌套組被celko推廣,但該方法被記入Michael J. Kamfonas(http://en.wikipedia.org/wiki/Joe_Celko)。 – onedaywhen 2009-04-20 08:33:51
Access中可以創建一個查詢來查找給定作業的根。 不要忘記VBA功能的力量。您可以在VBA模塊中創建遞歸函數,並將其結果用作查詢中的輸出字段。
例子:
Public Function JobRoot(Id As Long, ParentId As Long) As Long
If ParentId = 0 Then
JobRoot = Id
Exit Function
End If
Dim Rst As New ADODB.Recordset
Dim sql As String
sql = "SELECT Id, ParentID FROM JobTable WHERE Id = " & ParentId & ";"
Rst.Open sql, CurrentProject.Connection, adOpenKeyset, adLockReadOnly
If Rst.Fields("ParentID") = 0 Then
JobRoot = Rst.Fields("Id")
Else
JobRoot = JobRoot(Id, Rst.Fields("ParentID")) ' Recursive.
End If
Rst.Close
Set Rst = Nothing
End Function
您可以使用查詢生成器或函數名在查詢字段變量只是打字調用從查詢這個遞歸函數。
它會產生根。
(我承認OP現在已經一歲了,但我不得不在每個人都說不可能的時候回答)。
好吧,這是真正的交易。首先,您的查詢的目標受衆是什麼?表單?報告?功能的/ proc?
窗體:需要更新?使用樹視圖控件雖然笨拙,它將很好地工作。 報告:在打開的事件中,使用參數表單來設置「Boss作業」級別,然後處理vba中的遞歸併使用數據以所需的順序填充記錄集。將報告記錄集設置爲此填充的記錄集並處理報告。 函數/過程:與上面報告中描述的數據加載幾乎相同。通過代碼,處理必要的「樹行走」,並將結果集按需要的順序存儲在記錄集和進程中。
這不能在Access中使用純SQL來完成,但有點VBA有很長的路要走。
添加到Microsoft腳本運行時參考(工具 - >引用...)。
這假設ID是唯一的,並且沒有周期:例如, A的父母是B,但B的父母是A.
Dim dict As Scripting.Dictionary
Function JobRoot(ID As Long) As Long
If dict Is Nothing Then
Set dict = New Scripting.Dictionary
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT ID, ParentID FROM Job", dbOpenForwardOnly, dbReadOnly)
Do Until rs.EOF
dict(rs!ID) = rs!ParentID
rs.MoveNext
Loop
Set rs = Nothing
Dim key As Variant
For Each key In dict.Keys
Dim possibleRoot As Integer
possibleRoot = dict(key)
Do While dict(possibleRoot) <> 0
possibleRoot = dict(possibleRoot)
Loop
dict(key) = possibleRoot
Next
End If
JobRoot = dict(ID)
End Function
Sub Reset() 'This needs to be called to refresh the data
Set dict = Nothing
End Sub
Zev的貢獻給了我很大的啓發和學習。但是,需要對代碼進行一些編輯。請注意,我的表格被稱爲「tblTree」。
Dim dict As Scripting.Dictionary
Function TreeRoot(ID As Long) As Long
If dict Is Nothing Then
Set dict = New Scripting.Dictionary ' Requires Microsoft Scripting Runtime
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("tblTree", dbOpenForwardOnly, dbReadOnly)
Do Until rs.EOF
dict.Add (rs!ID), (rs!ParentID)
rs.MoveNext
Loop
Set rs = Nothing
End If
TreeRoot = ID
Do While dict(TreeRoot) <> 0 ' Note: short version for dict.item(TreeRoot)
TreeRoot = dict(TreeRoot)
Loop
End Function
並且在相同的上下文中還有另一個有用的功能。 如果在任何級別的嵌套中,孩子的匹配所提供的ParentID,則「ChildHasParent」返回true。
Function ChildHasParent(ID As Long, ParentID As Long) As Boolean
If dict Is Nothing Then
Set dict = New Scripting.Dictionary ' Requires Microsoft Scripting Runtime
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("tblTree", dbOpenForwardOnly, dbReadOnly)
Do Until rs.EOF
dict.Add (rs!ID), (rs!ParentID)
rs.MoveNext
Loop
Set rs = Nothing
End If
ChildHasParent = False
Do While dict(ID) <> 0 ' Note: short version for dict.item(TreeRoot)
ID = dict(ID)
If ID = ParentID Then
ChildHasParent = True
Exit Do
End If
Loop
End Function
當你說「工作可以在幾個大的孩子級別」或者粘貼一些虛擬數據時,請更精確一些。 – 2009-04-18 06:32:46