2011-01-07 82 views
2

(JobPath)再帰クエリ(階層的ではない)

JobId - ParentJobId 

あなたはその上のジョブ3にして、仕事を4に行くとジョブ2へのジョブ4件のリンクを見ることができるように私には、以下のデータ今

JobId - ParentId 
    1  2 
    2  3 
    3  4 
    4  2 

になってしまったまで完璧に働いたからデータを取得します。

既に持っているデータを引き出さないように私のクエリに伝える方法はありますか?ここで


私の現在のクエリ

WITH JobPathTemp (JobId, ParentId, Level) 
AS 
(
-- Anchor member definition 
    SELECT j.JobId, jp.ParentJobId, 1 AS Level 
    FROM Job AS j 
    LEFT OUTER JOIN dbo.JobPath AS jp 
     ON j.JobId = jp.JobId 
    where j.JobId=1516 
    UNION ALL 
-- Recursive member definition 
    SELECT j.JobId, jp.ParentJobId, Level + 1 
    FROM dbo.Job as j 
    INNER JOIN dbo.JobPath AS jp 
     ON j.JobId = jp.JobId 
    INNER JOIN JobPathTemp AS jpt 
     ON jpt.ParentId = jp.JobId 
     WHERE jp.ParentJobId <> jpt.JobId 
) 

ある - このソリューションが動作しないCTEを実行ステートメント

SELECT * FROM JobPathTemp 
+0

クエリはどのように見えますか?あなたはDistinctを使用できませんか? – Kell

+0

"再帰的な共通テーブル式 'JobPathTemp'の再帰的な部分では、DISTINCT演算子は使用できません。 –

答えて

3

を多数のエントリを処理するのではなく、以下の解決策が適切かもしれません。アイデアは、各行に完全な "IDパス"を作成し、(再帰部分の)現在のIDが処理中のパスにまだ存在しないことを確認することです:

基本パターンは同じである必要があります)

 
WITH JobPathTemp (JobId, ParentId, Level, id_path) 
AS 
(
    SELECT jobid, 
     parentid, 
     1 as level, 
     '|' + cast(jobid as varchar(max)) as id_path 
    FROM job 
    WHERE jobid = 1 

    UNION ALL 

    SELECT j.JobId, 
      j.parentid, 
      Level + 1, 
      jpt.id_path + '|' + cast(j.jobid as varchar(max)) 
    FROM Job as j 
    INNER JOIN JobPathTemp AS jpt ON j.jobid = jpt.parentid 
            AND charindex('|' + cast(j.jobid as varchar), jpt.id_path) = 0 
) 
SELECT * 
FROM JobPathTemp 
; 
+0

データ量には限界がありますので、この解決策はうまくいくはずです。私はDISTINCTが奇妙であるが削除していない重複をたくさん得ている。しかし、私のC#コードは、それほど大きな手間をかけずに処理できます。 –

+0

ちょうど私のDISTINCTの問題が無関係であることを見た..これは完全に動作します:) –

0

、SQL Serverが参加することUNIONを使用してサポートしていません。一緒に再帰的な用語。あなたが参加される場合を除き、再帰を参照することができないので、TBH、私はあなたのクエリを投稿していなかった


...保存された機能を使用して任意の代替を参照してください...しかし、私はありません(ほとんど同じように動作しますpostgresの、に)しようとしたあなたは、再帰的な用語では「UNION」(ない「UNION ALL」)を使用している場合、それは自動的に重複行削除する必要があります。あなたがいる場合

with /*recursive*/ jobs as 
(select jobpath.jobid, jobpath.parentjobid from jobpath where jobid = 1 
    union 
    select jobpath.jobid, jobpath.parentjobid 
    from jobpath 
     join jobs on jobs.parentjobid = jobpath.jobid 
) 
select jobpath.* from jobpath join jobs on jobpath.jobid = jobs.jobid; 
+0

ユニヴァーサルに変更すると今すぐクエリを追加しました "再帰的な共通テーブル式 'JobPathTemp'にはトップレベルのUNION ALL演算子が含まれていません。 –

+0

これは良い兆候ではありません。また、再帰的な項を2回指定することはできません。 WHERE NOT EXISTS句を使用します。 – araqnid

+0

いいえ私もそれを試しましたが、私はJobPathTempを2度参照してもエイリアスを参照するとエラーがスローされます –

関連する問題