조건

2009-09-25 7 views
0

내가 가지고있는 MS SQL에서 재귀 테이블 반환 함수 다음, 데이터베이스에서 개체의 계층 구조를 검색하기 위해 :조건


WITH tmpField (ParentNum, ChildNum, FieldNum, FieldDescr, Iteration) AS 
(
    SELECT Field.ParentNum, Field.ChildNum, Field.FieldNum, Field.FieldDescr, 1 
    FROM Field 
    WHERE Field.ParentNum = @ParentNum 

    UNION ALL 

    SELECT Field.ParentNum, Field.ChildNum, Field.FieldNum, Field.FieldDescr, tmpField.Iteration + 1 
    FROM Field INNER JOIN 
    tmpField on Field.ParentNum = tmpField.ChildNum 
) 
SELECT DISTINCT ParentNum AS ParentNum, ChildNum AS ChildNum, FieldNum, FieldDescr 
FROM tmpField 
나는 다음과 같은 방법으로 그것을 수정할

: 마지막 반복에서

, 더 이상 '어린이'가, 나는 ChildNum 필드 FieldNum의 가치를 갖고 싶어. 이전의 모든 반복에서 ChildNum의 값은 ChildNum 필드의 값이어야합니다.

누구든지 위의 쿼리를 시작점으로 사용하여이를 달성 할 수있는 방법을 제안 할 수 있습니까?

참고 : 해당 이름에도 불구하고 ChildNum 필드는 행의 하위를 참조하지 않지만 해당 행의 식별자로 해석되어야합니다. 더 이상 아이가 존재하지 않는 경우

답변

2

는 ChildNum이 NULL 너무 것을 의미 :

... 

UNION ALL 

    SELECT Field.ParentNum, 
     COALESCE(Field.ChildNum, Field.FieldNum) ChildNum, 
     Field.FieldNum, 
     ... 

편집 :이 경우, 우리는 ChildNum에

확인을 확인할 수 있습니다

(Daan 코멘트 다음) '어린이 수 :

... 

    UNION ALL 

     SELECT F1.ParentNum, 
      CASE WHEN (SELECT COUNT(1) 
          FROM FIELD F2 
         WHERE F2.ParentNum = F1.ChildNum) = 0 
        THEN F1.FieldNum 
        ELSE F1.ChildNum 
      END ChildNum, 
      F1.FieldNum, F1.FieldDescr, tmpField.Iteration + 1 
     FROM Field F1 INNER JOIN 
     tmpField on F1.ParentNum = tmpField.ChildNum 

... 

EDIT2 :

이의 외부 검사를 이동하자가 :

WITH tmpField (ParentNum, ChildNum, FieldNum, FieldDescr, Iteration) AS 
(
    SELECT Field.ParentNum, Field.ChildNum, Field.FieldNum, Field.FieldDescr, 1 
    FROM Field 
    WHERE Field.ParentNum = @ParentNum 

    UNION ALL 

    SELECT Field.ParentNum, Field.ChildNum, Field.FieldNum, Field.FieldDescr, tmpField.Iteration + 1 
    FROM Field INNER JOIN 
    tmpField on Field.ParentNum = tmpField.ChildNum 
) 
SELECT DISTINCT ParentNum AS ParentNum, 
       CASE WHEN EXISTS (SELECT NULL 
            FROM Field f 
            WHERE tmpField.ChildNum = f.ParentNum) 
         THEN tmpField.ChildNum 
         ELSE tmpField.FieldNum 
       END ChildNum, 
       FieldNum, 
       FieldDescr 
FROM tmpField 
+0

(사용하도록 수정 대신 COUNT 존재합니다) 반복을 제거 이 경우 ChildNum은 null이 아닙니다. 다른 행에 대한 참조가 아닌 현재 행의 식별자로 ChildNum을 읽어야합니다. 명명 규칙은 어색합니다. 아시다시피, 불행히도 내 통제에서 벗어났습니다. :) – Daan

+0

편집은이 작업을 수행하는 좋은 방법 인 것처럼 보입니다. 불행히도, 내 함수를 변경하려고하면 다음과 같은 오류가 발생합니다. GROUP BY, HAVING 또는 집계 함수는 재귀 공통 테이블 식 'tmpField'의 재귀 부분에서 허용되지 않습니다. 해결 방법에 대한 제안 사항이 있습니까? – Daan

+0

대신 CASE의 WHEN (SELECT COUNT (1) ...) = 0 THEN FieldNum ELSE ChildNum END 당신은 CASE를 언제 사용해야 존재 (SELECT * FROM ...) THEN ChildNum ELSE FieldNum 끝 두 번째 것보다 빠릅니다. – Niikola

1

이 당신이 필요로하는 데이터를 반환해야합니다. 나중에

이 버전 가입 당신이 그것을 사용하지 않는 나는

;WITH tmpField (ParentNum, ChildNum, FieldNum, FieldDescr) AS 
(
    SELECT f.ParentNum, f.ChildNum, f.FieldNum, f.FieldDescr 
    FROM Field f 
    WHERE f.ParentNum = @ParentNum 
    UNION ALL 
    SELECT f.ParentNum, f.ChildNum, f.FieldNum, f.FieldDescr 
    FROM Field f 
    INNER JOIN tmpField on f.ParentNum = tmpField.ChildNum 
) 
SELECT t.ParentNum AS ParentNum, 
     Case When p.ParentNum is Null 
      Then t.FieldNum 
      Else t.ChildNum 
     End AS ChildNum, 
     t.FieldNum, 
     t.FieldDescr 
FROM tmpField t 
Left Join (Select distinct ParentNum From Field) p on t.ChildNum=p.ParentNum 

또는

하위 쿼리 버전 불행하게도, 아니

;WITH tmpField (ParentNum, ChildNum, FieldNum, FieldDescr) AS 
(
    SELECT f.ParentNum, f.ChildNum, f.FieldNum, f.FieldDescr 
    FROM Field f 
    WHERE f.ParentNum = @ParentNum 
    UNION ALL 
    SELECT f.ParentNum, f.ChildNum, f.FieldNum, f.FieldDescr 
    FROM Field f 
    INNER JOIN tmpField on f.ParentNum = tmpField.ChildNum 
) 
SELECT t.ParentNum AS ParentNum, 
     Case When Exists(Select * from Field p Where t.ChildNum=p.ParentNum) 
      Then t.ChildNum 
      Else t.FieldNum 
     End AS ChildNum, 
     t.FieldNum, 
     t.FieldDescr 
FROM tmpField t 
+0

위에 게시 된 쿼리 perfents는 COUNT를 사용하는 솔루션보다 두 배 빠릅니다. – Niikola