Frage

Ich habe eine job Tabelle

Id
ParentID
jobName
jobStatus

Die Wurzel ParentID ist 0.

Ist es möglich, in Access eine Abfrage zu erstellen, eine Wurzel für einen bestimmten job zu finden? Die Datenbank wird ohne verknüpften Tabellen MDB. Die Access-Version ist 2003. Ein job können mehrere Ebenen große Kinder tief sein.

War es hilfreich?

Lösung

Nein, ist es nicht. Rekursive Abfragen werden in SQL Server nach sServer 2005 unterstützt, aber nicht in Access.

Wenn Sie die Anzahl der Ebenen im Voraus wissen, können Sie eine Abfrage schreiben, aber es wäre eine rekursive man nicht sein.

In SQL Server, CTE (Eine SQL-Erweiterung) ist dafür verwendet: siehe http://blog.crowe.co.nz/archive/2007/09/06/Microsoft-SQL-Server-2005 --- CTE-Beispiel-of-a-simple.aspx

Regelmäßige SQL jedoch nicht über Rekursivität Unterstützung.

Andere Tipps

Es ist möglich, in Access eine Abfrage zu erstellen, die Wurzel Ihres bestimmten Jobs zu finden. Vergessen Sie nicht die Macht der VBA-Funktionen. Sie können eine rekursive Funktion in einem VBA-Modul erstellen und das Ergebnis als Ausgabefeld in der Abfrage verwenden.

Beispiel:

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

Sie können diese rekursive Funktion aus der Abfrage aufrufen, indem Sie den Query Builder verwendet oder nur mit Argumenten in einem Abfragefeld im Funktionsnamen eingeben.

Es wird die Wurzel erhalten.

(Ich erkenne das OP ein Jahr alt jetzt ist, aber ich bin gezwungen, um zu antworten, wenn jeder sagt, was ist unmöglich möglich ist).

Sie können nicht rekursiv abgefragt werden.

Sie können entweder tun einige beliebige Anzahl von links schließt sich, aber Sie werden nur in der Lage sein, so viele Ebenen zu gehen, wie Sie haben beitritt.

Oder Sie benutzen Celko der "Nested Sets" um alle Eltern zurückzuholen. Dies erfordert Ihre Tabellenstruktur ändern, in Art und Weise, die Einfügungen und Aktualisierungen komplizierter macht.

Das kann nicht mit reinem SQL in Access getan werden, aber ein wenig VBA geht einem langen Weg.

Fügen Sie einen Verweis auf die Microsoft Scripting Runtime . ( Extras -> Referenzen ... )

Dies setzt voraus, dass die ID eindeutig ist, und dass es keine Zyklen: z.B. Eine der Eltern ist B, aber B der Eltern ist 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

OK also hier ist die eigentliche Behandlung. Erstens, was ist die Zielgruppe für Ihre Anfrage .. ein Formular? Bericht? Funktion / proc?

Form: Need-Updates? Verwenden Sie die treeview Steuerung während ungeschickt es schön funktioniert. Bericht: im offenen Ereignisse einen Parameter Formular verwenden, um die „Boss Job“ Pegel setzen dann die Rekursion in vba handhaben und einen Re-Cord mit den Daten in der gewünschten Reihenfolge füllen. stellen Sie die Berichte Cord-Set zu diesem gefüllt Cord-Set und verarbeiten den Bericht.  Funktion / Prozedur: funktioniert so ziemlich das gleiche wie eine die Datenlast im Bericht beschrieben. Durch Code, behandelt den notwendigen „Baum walking“ und speichern Sie das Ergebnis gesetzt in der gewünschten Reihenfolge in einem Re-Cord und Prozess nach Bedarf.

Zev Beitrag hat mir viel Inspiration und Lernen. Allerdings benötigt, um einige Änderungen an dem Code zu tun. Bitte beachten Sie, dass mein Tisch „tblTree“ genannt wird.

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

Und es ist eine weitere nützliche Funktion im selben Kontext. „ChildHasParent“ gibt true zurück, wenn das Kind das mitgelieferte ParentID in jeder Ebene der Verschachtelung entspricht.

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top