私は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-99」と区別するために、「ISO/ANSI標準SQL」に接尾辞年を付ける必要がありますか? –
再帰的にクエリを実行することはできません。
任意の数の左ジョインを行うこともできますが、ジョインしたレベルだけ上げることができます。
Celko's "Nested Set Model"を使用すると、すべての親を取得できます。これにより、挿入と更新がより複雑になるように、テーブル構造を変更する必要があります。
再帰的にクエリを実行することはできません。 - >アクセス03には、とにかく、他の多くのクエリlangsにすることができます – Peter
はい、 "あなた" OPを使用している人は、再帰的にクエリすることはできません。 – tpdi
ネストされたセットはCelkoによって一般化されましたが、このメソッドはMichael J. Kamfonas(http://en.wikipedia.org/wiki/Joe_Celko)に入金されます。 – onedaywhen
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が1歳であることを認識していますが、誰もが不可能なことを言うときに私は答えなければなりません)。
私はあなたの投稿に拍手を送っていますが、元の質問は実際にはVBAなしでは不可能な質問に対する答えを実際に制限しています。 「クエリで」を「カスタムVBA関数に依存しない」と解釈するのが公正であるかどうかは別の問題です。同じ問題を抱えている他の人たちが純粋なSQLの答えではないという脅威がないので、元のポスターが探していたものではないにしても、あなたのソリューションをここに置くことは良いことだと思います。 –
これは、呼び出されるたびに新しいレコードセットを開くことを意味するため、非常に非効率的です。私は最低でも、モジュールレベルの変数でレコードセットを保持するか、レコードセット全体をメモリ内のモジュールレベルのScripting.Dictionaryにロードすることをお勧めします。これは、[this](http:// stackoverflow)のような高速アクセスを可能にします。 com/a/32161506)。 @ David-W-Fenton –
OKこれが本当のところです。最初に、あなたの質問のターゲットオーディエンスは何ですか?フォーム?報告する?関数/ proc?
フォーム:更新が必要ですか?それはうまく動作して不器用な間にtreeviewコントロールを使用してください。 Report:openイベントでパラメータフォームを使用して "Boss Job"レベルを設定し、次にVBAの再帰を処理し、データのレコードセットを希望の順に入力します。このレコードセットにレポートレコードセットを設定し、レポートを処理します。 機能/手順:上記のレポートで説明したデータ読み込みとほぼ同じです。コードを使用して、必要な「ツリーウォーキング」を処理し、必要に応じて結果セットをレコードセットおよびプロセスに必要な順序で格納します。
どのようなTreeviewコントロールですか?私が知っているAccessのどのバージョンでも利用可能なネイティブTreeviewはありません。 –
これは既存の回答にはうってつけかもしれませんが、仕事が必要です。たとえば、「OK」を削除すると、実際の取引が表示されます。オプションを箇条書きまたはパラに分割します。それぞれを展開して明確にする。 –
これは、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
と同じコンテキスト内の別の便利な機能があります。 "ChildHasParent"は、子が任意の入れ子レベルの指定されたParentIDと一致する場合にtrueを返します。
"仕事がいくつかの壮大な子レベルにある"と言ったり、いくつかのダミーデータを貼り付けたりするときはもっと正確に記述してください。 –