2

나는 SQL 바이올린 here을 만들었습니다.교대 테이블을 사용하는 순환 CTE

기본적으로 테이블 3 개는 BaseTable, FilesLinkingTable입니다.

Files 테이블에는 PK, BaseTableId, RecursiveId (ChildId)의 세 열이 있습니다. 내가하고 싶은 일은 BaseTableId (즉, ParentId)이 주어진 모든 아동을 찾는 것입니다. 까다로운 부분은 아이들이이 같은 작품을 발견하는 방법이다 :

FileId가 보는 것을 사용 ParentId (BaseTable.BaseTableId) 1을 가지고 다음의 Files 테이블에 FileId을 찾아 볼 것을 사용하십시오 ChildId (LinkingTable.RecursiveId)가 LinkingTable 인 경우 해당 레코드가 존재하면 의 RecursiveId을 사용하여 Files 테이블의 다음 FileId을 찾습니다.

이는 지금까지 내 CTE이다

with CTE as 
(
    select lt.FileId, lt.RecursiveId, 0 as [level], 
     bt.BaseTableId 
    from BaseTable bt 
    join Files f 
    on bt.BaseTableId = f.BaseTableId 
    join LinkingTable lt 
    on f.FileId = lt.FileId 
    where bt.BaseTableId = @Id 
    UNION ALL 
    select rlt.FileId, rlt.RecursiveId, [level] + 1 as [level], 
     CTE.BaseTableId 
    from CTE --??? and this is where I get lost 
... 
) 

BaseTableId = 1에 정확한 출력은 같아야

FileId|RecursiveId|level|BaseTableId 
    1  1   0  1 
    3  2   1  1 
    4  3   2  1 

표 관계

Table Relationship

+0

샘플 데이터뿐만 아니라 원하는 결과가 문제를 설명하기위한 매우 유용 할 것입니다. –

+1

@ GordonLinoff 질문 상단에 바이올린 링크가 있습니다 – SOfanatic

+0

SQLFiddle 열 이름이 위의 예제 쿼리에서 열 이름과 일치하면 유용합니다. 현재 SQLFiddle의 BaseTable에는 UniqueId int, FKId int 열이 있습니다. 나는 UniqueId = BaseTableId이고 FKId = FileId라고 가정하고 있습니까? – BateTech

답변

1

H ere는 귀하의 기준을 충족한다고 생각하는 재귀적인 예입니다. 부모가 없으므로 결과 집합에 ParentId을 추가했습니다. 루트/기본 파일에는 NULL이됩니다.

declare @BaseTableId int; 
set @BaseTableId = 1; 

; WITH cteRecursive as (
    --anchor/root parent file 
    SELECT null as ParentFileId 
     , f.FileId as ChildFileID 
     , lt.RecursiveId 
     , 0 as [level] 
     , bt.BaseTableId 
    FROM BaseTable bt 
     INNER JOIN Files f 
      on bt.BaseTableId = f.BaseTableId 
     INNER JOIN LinkingTable lt 
      on f.FileId = lt.FileId 
    WHERE bt.BaseTableId = @BaseTableId 

    UNION ALL 

    SELECT cte.ChildFileID as ParentFileID 
     , f.FileId as ChildFileID 
     , lt.RecursiveId 
     , cte.level + 1 as [level] 
     , cte.BaseTableId 
    FROM cteRecursive cte 
     INNER JOIN Files f on cte.RecursiveId = f.RecursiveId 
     INNER JOIN LinkingTable lt ON lt.FileId = f.FileId 
) 
SELECT * 
FROM cteRecursive 
; 

@BaseTableID = 1에 대한 결과 : @BaseTableID = 2

ParentFileId ChildFileID RecursiveId level  BaseTableId 
------------ ----------- ----------- ----------- ----------- 
NULL   1   1   0   1 
1   3   2   1   1 
3   4   3   2   1 

결과 :

ParentFileId ChildFileID RecursiveId level  BaseTableId 
------------ ----------- ----------- ----------- ----------- 
NULL   2   1   0   2 
NULL   2   4   0   2 
2   6   5   1   2 
6   7   6   2   2 
2   3   2   1   2 
3   4   3   2   2 
+0

이것은 OP의 예상 출력과 일치하지만 질문이 있습니다. FileId 5가 BaseTableID 1의 자식으로 나타나야합니까? Files.FileID 4는 OP 예상 출력의 마지막 행입니다. LinkingTable.FileID = 4의 행은 LinkingTable.RecursiveId 값이 3이며 Files.ResursiveID = 3에 다시 연결되며 해당 행의 Files.FileId 값은 5입니까? Files.FileId 5는 LinkingTable의 FileId와 다시 일치하지 않지만 업데이트 된 질문의 다이어그램에 따르면 BaseTableId 1의 하위 파일로 계속 나타나야합니다. – BateTech

+0

FileId 5가 표시되지 않아야합니다. BaseTableId 1에 대한 자식이 LinkingTable에 없으므로 파일이 LinkingTable에있는 경우 "사용되었습니다"라는 의미이므로 어쨌든 "사용 된"모든 파일을 찾고 있습니다. 결론적으로 FileId 5는 BaseTableId 1의 자식이지만 "사용되지"않았으므로 결과의 일부가 아니어야합니다. – SOfanatic