У вас есть несколько вариантов. Один, однако, не подойдет, и это рекурсивный запрос, использующий только SQL;Доступ не может быть одурачен и потребует циклическую ссылку. Ваш единственный шанс - создать запрос, разрешающий только ограниченное количество уровней, скажем, 8 или 10.
Но вы можете покрыть рекурсивный вызов в агрегатной функции домена, такой как DLookup
. Это, однако, очень медленно, так как DLookup
вызов запроса будет выполняться для каждой записи. Для более чем нескольких десятков записей это, скорее всего, будет неприемлемо.
Самый быстрый способ для неограниченного числа уровней, как я обнаружил, - это создать функцию поиска, которая обходит дерево для каждой записи. Это может выводить либо уровень записи, либо составной ключ, построенный по ключу записи и всем указанным ключам.
Поскольку функция поиска будет использовать один и тот же набор записей для каждого вызова, вы можете сделать это static , и (для JET / ACE) вы можете улучшить ситуацию, используя Seek
для поиска записей.
Вот пример, который даст вам представление:
Function RecursiveLookup(ByVal lngID As Long) As String
Static dbs As Database
Static tbl As TableDef
Static rst As Recordset
Dim lngLevel As Long
Dim strAccount As String
If dbs Is Nothing Then
' For testing only.
' Replace with OpenDatabase of backend database file.
Set dbs = CurrentDb()
Set tbl = dbs.TableDefs("tblAccount")
Set rst = dbs.OpenRecordset(tbl.Name, dbOpenTable)
End If
With rst
.Index = "PrimaryKey"
While lngID > 0
.Seek "=", lngID
If Not .NoMatch Then
lngLevel = lngLevel + 1
lngID = !MasterAccountFK.Value
If lngID > 0 Then
strAccount = str(!AccountID) & strAccount
End If
Else
lngID = 0
End If
Wend
' Leave recordset open.
' .Close
End With
' Don't terminate static objects.
' Set rst = Nothing
' Set tbl = Nothing
' Set dbs = Nothing
' Alternative expression for returning the level.
' (Adjust vartype of return value of function.) ' RecursiveLookup = lngLevel ' As Long
RecursiveLookup = strAccount
End Function
Предполагается, что таблица с первичным ключом ID и внешним (главным) ключом, указывающим на родительскую запись, и запись верхнего уровня (не используется) с видимым ключом ( AccountID * 1020). *) из 0.
Теперь ваше дерево будет отображаться почти мгновенно, используя такой запрос, где Account будет видимым составным ключом:
SELECT
*, RecursiveLookup([ID]) AS Account
FROM
tblAccount
WHERE
AccountID > 0
ORDER BY
RecursiveLookup([ID]);