2013-12-22 1 views
0

나무의 첫 번째 일치 노드로 결과를 제한하기 :내가 acts_as_ordered_tree 보석에서이 SQL 출력이

이 쿼리 내가왔다 component_instances을 보여주고 싶은 휴지통위한 것입니다
SELECT "component_instances".* 
FROM "component_instances" 
INNER JOIN (
    WITH RECURSIVE descendants AS ( 
     SELECT id, parent_id, ARRAY[position] AS _positions 
     FROM "component_instances" 
     WHERE "component_instances"."id" = 1 
     UNION ALL 
     SELECT alias1.id, alias1.parent_id, _positions || alias1.position 
     FROM descendants 
     INNER JOIN "component_instances" alias1 
       ON alias1.parent_id = descendants.id 
    ) 
    SELECT * FROM descendants 
) AS descendants 
ON descendants.id = component_instances.id 
WHERE ("component_instances"."id" != 1) 
    AND (component_instances.archived_at IS NOT NULL 
    AND component_instances.archive_number IS NOT NULL) 
ORDER BY descendants._positions ASC 

'아카이브 됨'(쿼리 마지막의 마지막 조건 참조) 원래 삭제 된 상위 항목을 먼저 복원하지 않으면 이러한 노드를 논리적으로 복원 할 수 없기 때문에 보관 된 component_instance의 하위 항목을 표시하고 싶지 않습니다.

이 쿼리를 수정하는 동안 문제가 발생하여 보관 노드가 발견 될 때 반복되지 않지만 여전히 결과에 해당 노드가 포함됩니다.

답변

0

나는 나는 내가 제대로 질문을 이해한다면,
내가 예를 사용하여 내 이해를 보여주기 위해 노력할 것이다 아주 확실하지 :

| ID | PARENT_ID | POSITION | ARCHIVED_AT | ARCHIVE_NUMBER | 
|----|-----------|----------|-------------|----------------| 
| 1 | (null) | (null) |  (null) |   (null) | 
| 2 |   1 | (null) |  (null) |   (null) | 
| 3 |   1 | (null) |   1 |    1 | <== archived 
| 21 |   2 | (null) |  (null) |   (null) | 
| 22 |  21 | (null) |  (null) |   (null) | 
| 31 |   3 | (null) |  (null) |   (null) | <== children of 3 
| 32 |  31 | (null) |  (null) |   (null) | <== children of 3 

:

테이블 component_instances는 다음과 같은 레코드가 말 알다시피, 쿼리는 "보관 된"레코드 인 id=3을 검색 할 것으로 예상됩니다.
id=31id=32의 레코드를 건너 뛸 필요가 있습니다. "보관 된"레코드 id=3.

WITH RECURSIVE descendants AS ( 
     SELECT id, parent_id, ARRAY[position] AS _positions, 
      /* new column */ 
      archived_at 
     FROM "component_instances" 
     WHERE "component_instances"."id" = 1 
     UNION ALL 
     SELECT alias1.id, alias1.parent_id, _positions || alias1.position, 
      /* new column */ 
      alias1.archived_at 
     FROM descendants 
     INNER JOIN "component_instances" alias1 
       ON alias1.parent_id = descendants.id 
     /* new condition - the parent record is not archived */ 
     WHERE descendants.archived_at is null 
) 
SELECT * FROM descendants 
; 

데모 (참조 : 나의 이해가 올 경우 가입 후 부모 레코드의 archived_at가 null NUL인지 여부

, 다음, SELECT 절에
을 추가로 열 archived_at를 추가하고 확인 이 데모의 마지막 쿼리) ->http://www.sqlfiddle.com/#!15/033a7/6

+0

감사합니다. 멋지고 간결하며 완벽하게 작동합니다. 원래 쿼리의 마지막 부분을 중단하여 쿼리에서 삭제 된 부모보다 상위의 부모도 반환하도록했습니다. 내 쿼리의 목적은 삭제 된 (보관 된) 노트에서 자녀를 뺀 값만 반환하는 것이 었습니다. 나머지 쿼리를 끝에 추가하는 것만으로이 문제를 해결할 수 있습니다. 이것을 보여주기 위해 답을 업데이트하고 싶습니까? –