2013-08-03 1 views
4

나는 leafs를 가진 간단한 테이블을 가지고 있고 sub는 info를 leafs한다. childIdParentID 우리가이 주요 질문과 답변을 참조 그래서 여기 재귀 CTE에 대해 두 개 이상의 결과 집합을 가져 옵니까?

enter image description here

같은

을 어디에

(포럼 질문 같이) 주요 메시지가 정의된다. 이 메인 쿼리입니다 한마디로

enter image description here

:

가 나는 또한 각 요소의 깊이를 CALC 관리했습니다

WITH CTE AS 
    (
     SELECT childID 
      ,parentID, 
      0 AS depth,name 
     FROM @myTable 
     WHERE childID = parentID AND childID=1 -- problem line 

     UNION ALL 

     SELECT TBL.childID 
      ,TBL.parentID, 
       CTE.depth + 1 , TBL.name 
     FROM @myTable AS TBL 
       INNER JOIN CTE ON TBL.parentID = CTE.childID 
     WHERE TBL.childID<>TBL.parentID 
    ) 
    SELECT childID,parentID,REPLICATE('----', depth) + name   

그러나 문제는 라인 # 8 (주석). 나는 현재 에게

그래서 문제가 "나에게 질문 ID # 1에 대한 모든 클러스터를 준다"?

각 질문마다 복수 결과를 갖고 싶습니다!

그래서 여기에 나는이 개 결과 집합이 필요합니다 : childId=parentId=6

full working sql online

에 대한 하나

childId=parentId=1 하나 하나를 (내가 커서를 사용하려는 해달라고)

+0

어떤 이유로 여러 레코드 집합 (모든 질문에 대해 하나의 레코드 집합)을 원하십니까? –

+0

각 질문은 html repeater에 바인드되어 있습니다. 그 이유는 무엇입니까? 각 질문마다 다른 조작을해야합니다. –

+0

여러 결과 세트를 원할 경우 커서를 사용하지 않으시겠습니까? SQL Server가 단일 집합으로 동작하는 동안 여러 결과 집합을 나타내는 방법이 있다고 생각합니까? 커서가 수행하려고하는 접근 방식에 어떤 성능 문제가 추가 될 것이라고 생각하십니까? –

답변

8

클라이언트에 여러 결과 집합을 제시하려면, 당신은 커서 나 독립 SELECT 작업을 수행하는 동안 루프를 사용해야 할 것입니다. CTE는 정확히 하나의 후속 쿼리에서만 사용할 수 있기 때문에 CTE에서이를 수행 할 수 없습니다.

이제 문제의 원인은 커서와 관련이 없지만 HTML 중계기를 사용하고 있다는 사실입니다. 왜 HTML 중계기를 사용해야합니까? 간단한 DataReader는 CTE의 단일 집합의 모든 결과를 반복하고 루프를 기반으로 조건부 서식을 결정하고 루트 ID가 변경되는시기를 결정할 수 있습니다. 따라서 프리젠 테이션 구현을 수용하기 위해 SQL Server를 강요하는 대신 프리젠 테이션 문제를 해결하는 방법을 살펴 보는 것이 좋습니다.

+0

http://i.stack.imgur.com/iitmS.png –

+2

@RoyiNamir 이미지가 표시되지만 단일 결과 세트로 해당 프리젠 테이션을 생성 할 수 없다는 것을 이해하지 못합니다. 필요한 HTML을 생성하기 위해 클라이언트 측 코드에 더 많은 논리가 필요하고, 아마도'n' HTML 중계기를 사용하는 것보다 더 효율적일 것입니다. –

+0

"필요한 HTML_을 생성하는 클라이언트 측 코드에서 _more 로직이 있습니다."문제가 없습니다. "SQL이 모든 작업을 수행하고 모든 데이터를 소화하도록하십시오." –

-2

루트 질문의 앵커 부분 childId에 저장 한 다음 필요에 따라 모든 분기에 액세스 할 수 있습니다. D :

WITH CTE AS (
    SELECT childID as RootId 
     , childID 
     , parentID 
     , 0 AS depth,name 
    FROM @myTable 
    WHERE childID = parentID 
    UNION ALL 
    SELECT CTE.RootId 
     , TBL.childID 
     , TBL.parentID 
     , CTE.depth + 1 , TBL.name 
    FROM @myTable AS TBL 
    INNER JOIN CTE ON TBL.parentID = CTE.childID 
    WHERE TBL.childID<>TBL.parentID 
) 
+0

이것은 어떻게 여러 개의 독립 결과 집합을 반환합니까? 쿼리를 마칠 수 있습니까? –

+0

이 쿼리는 "있는 그대로"여러 결과 집합을 반환하지 않습니다. 그러나 필요할 때마다 필요한 ID로 액세스 할 수 있습니다. SELECT * FROM CTE WHERE RootId = 1 UNION ALL SELECT * FROM CTE WHERE RootId = 6 – GriGrim

+0

어떻게 표시 할 수 있습니까? 그렇지 않으면 OP가 이미 보유하고있는 CTE와 다른 점이 무엇인지 잘 모르겠습니다. 또한 처음 질문에 영향을 미치는 실제 요구 사항을 충족시키는 방법을 명확히하지 않았습니다. –

9

동적으로 쿼리를 작성할 수 있습니다.

DECLARE @SQL NVARCHAR(MAX) = 
(SELECT ' 
WITH CTE AS 
(
    SELECT childID 
     ,parentID, 
     0 AS depth,name 
    FROM myTable 
    WHERE childID = parentID AND childID = '+CAST(childID AS NVARCHAR(10))+' 

    UNION ALL 

    SELECT TBL.childID 
     ,TBL.parentID, 
      CTE.depth + 1 , TBL.name 
    FROM myTable AS TBL 
      INNER JOIN CTE ON TBL.parentID = CTE.childID 
    WHERE TBL.childID<>TBL.parentID 
) 
SELECT childID,parentID,REPLICATE(''----'', depth) + name 
FROM CTE 
ORDER BY 
     childID;' 

FROM myTable 
WHERE childID = parentID 
FOR XML PATH(''), TYPE).value('text()[1]', 'NVARCHAR(MAX)'); 

EXEC sp_executesql @SQL; 

업데이트 : 우리가 매개 변수화 실제 쿼리를하여 컴파일을 최소화 할 수 있습니다 보그 Sahlean에 의해 제안

.

DECLARE @SQL1 NVARCHAR(MAX) = 
'WITH CTE AS 
(
    SELECT childID 
     ,parentID, 
     0 AS depth,name 
    FROM myTable 
    WHERE childID = parentID AND childID = @childID 

    UNION ALL 

    SELECT TBL.childID 
     ,TBL.parentID, 
      CTE.depth + 1 , TBL.name 
    FROM myTable AS TBL 
      INNER JOIN CTE ON TBL.parentID = CTE.childID 
    WHERE TBL.childID<>TBL.parentID 
) 
SELECT childID,parentID,REPLICATE(''----'', depth) + name 
FROM CTE 
ORDER BY 
     childID;' 

DECLARE @SQL2 NVARCHAR(MAX) = 
(SELECT 'exec sp_executesql @SQL, N''@childID int'', '+CAST(childID AS NVARCHAR(10))+';' 
FROM myTable 
WHERE childID = parentID 
FOR XML PATH(''), TYPE).value('text()[1]', 'NVARCHAR(MAX)'); 

EXEC sp_executesql @SQL2, N'@SQL NVARCHAR(MAX)', @SQL1; 
+4

이것은 테이블 변수와 함께 작동하지 않습니다. –

+0

매개 변수 ('WHERE ...childID = @ param')을 사용하여 계획 컴파일을 최소화하고 계획 재사용을 촉진합니다. –

+0

@Bogdan은 훨씬 더 복잡 할 것이며 중첩 된 동적 SQL이 필요하다고 생각합니다. 질의는 실제로 각기 다른 ChildID에 대해 하나씩 많은 CTE 쿼리를 생성합니다. 간단한 매개 변수를 사용하는 방법을 보여줄 수 있습니까? –

0

"두 개의 결과 집합을 반환하는 것"이 ​​무슨 뜻인지 잘 모르겠습니다. 하나의 결과 집합과 루트 질문을 다른 열에 할당 할 수 있습니까? 다음과 같이 쿼리를 수정하면 다음과 같이됩니다.

WITH CTE AS (
     SELECT ChildId as WhichQuestion, childID, parentID, 0 AS depth, name 
     FROM @myTable 
     WHERE childID = parentID 
     UNION ALL 
     SELECT cte.WhichQuestion, TBL.childID, TBL.parentID, CTE.depth + 1 , TBL.name 
     FROM @myTable AS TBL 
      INNER JOIN CTE ON TBL.parentID = CTE.childID 
     WHERE TBL.childID <> TBL.parentID 
    ) 
SELECT WhichQuestion, childID, parentID, REPLICATE('----', depth) + name  
FROM CTE 
ORDER BY WhichQuestion, childID; 
+0

그는 HTML 중계기를 가지고 있기 때문에 현재는 독립적 인 SELECT 문에서 출력이 필요합니다 (분명히 CTE에서 올 수 없습니다). 다행스럽게도 HTML 중계기를 만족시키기 위해 쿼리를 변경하는 대신 단일 결과 집합을 처리하기 위해 클라이언트 측 코드를 변경해야한다고 확신했습니다. –