0

그래프 :TSQL CTE와 같은 구조 및 샘플 데이터의 테이블을 정렬

GetActivities('a') 

Order Activities 
------------------- 
0  a 
1  b 
2  c 

I :

TableActivity 
------------- 
Type    VARCHAR(8) 
Activity   VARCHAR(8) 
RelatedActivity  VARCHAR(8) 

Type  Activity  RelatedActivity 
------------------------------------------ 
Start  a    - 
Transfer a    b 
Start  b    - 
Transfer b    c 
Start  c    - 
Stop  c    - 
Transfer c    b 
Stop  b    - 
Transfer b    a 
Stop  a    - 

CTE 쿼리를 작성할 수 있을까는 다음을 수행 할 재귀 문에서 행을 반환하는 것을 멈추는 데 어려움을 겪고 있습니다.

아이디어가 있으십니까?

편집

은 ('A'를) GetActivities을 명확히합니다. 이 함수는 'a'의 '시작'활동을 찾아 'a'의 '전송'활동을 찾아야합니다. 그 지점에서 함수는 'b'와 그 결과로 샘플 데이터와 함께 'c'를 반복 할 수 있습니다. 쿼리는 '전송'을 통해 'a'와 관련된 모든 활동을 반환해야합니다. 이 중첩 된 활동은 필요한만큼 깊게 갈 수 있고 알 수 없습니다 (그래서 노동 조합이 없음). 내가 가지고있는 어려움은 예를 들어 다른 '전송'이 다시 진행된다는 것입니다. 'b'-> 'a'. 재귀 쿼리에서 이것이 어떻게 생성되는지 볼 수 있습니다.

하나 더 설명 : 활동 표의 전송이 스택으로 작동합니다. 다음은 데이터가 테이블에 채워지는 방법입니다 (C#의 경우) :

using (Activity.Start("a")) 
{ 
    // transfer to 'b' under covers 
    using (Activity.Start("b")) 
    { 
    // transfer to 'c' under covers 
    using (Activity.Start("c")) 
    { 
    } 
    // transfer to 'b' under covers 
    } 
    // transfer to 'a' under covers 
} 

답변

1

:

declare @TableActivity table 
([Type]    VARCHAR(8) 
,Activity   VARCHAR(8) 
,RelatedActivity  VARCHAR(8) 
) 

insert @TableActivity 
     select 'Start','a','-' 
union select 'Transfer','a','b' 
union select 'Start','b','-' 
union select 'Transfer','b','c' 
union select 'Start','c','-' 
union select 'Transfer','c','d' 
union select 'Transfer','c','e' 
union select 'Start','d','-' 
union select 'Stop','d','-' 
union select 'Start','e','-' 
union select 'Stop','e','-' 
union select 'Transfer','d','c' 
union select 'Transfer','e','c' 
union select 'Stop','c','-' 
union select 'Transfer','c','b' 
union select 'Stop','b','-' 
union select 'Transfer','b','a' 
union select 'Stop','a','-' 
union select 'Start','1','-' 
union select 'Transfer','1','2' 
union select 'Start','2','-' 
union select 'Transfer','2','3' 
union select 'Start','3','-' 
union select 'Transfer','3','4' 
union select 'Start','4','-' 
union select 'Stop','4','-' 
union select 'Transfer','4','3' 
union select 'Stop','3','-' 
union select 'Transfer','3','2' 
union select 'Stop','2','-' 
union select 'Transfer','2','1' 
union select 'Stop','1','-' 

declare @activity varchar(8) 
set @activity = 'a' 

;WITH ActivitiesGraph(activity, relatedactivity) AS 
(
     SELECT activity, 
      relatedactivity 
     FROM @TableActivity root 
     WHERE root.activity = @activity 
     AND root.type  = 'Transfer' 

     UNION ALL 

     SELECT next.activity, 
      next.relatedactivity 
     FROM @TableActivity next 
      INNER JOIN ActivitiesGraph prior 
      ON  next.activity = prior.relatedactivity 
     WHERE next.type   = 'Transfer' 
     AND prior.activity != next.relatedactivity 
     AND prior.activity != next.activity 
    ) 
SELECT activity 
FROM @TableActivity 
WHERE activity = @activity 

UNION 

SELECT relatedactivity 
FROM ActivitiesGraph 
+0

더 큰주기를 처리하지 않습니다. "UNION SELECT 'Transfer', 'c', 'a'"를 예제에 추가하십시오. –

+0

다행스럽게도이 경우는 내 애플리케이션에서 발생하지 않습니다. 액티비티 트래 버설은 스택처럼 작동합니다. – jsw

+0

아. 이것은 사이클이있는 일반 지향 그래프를 처리하는 훨씬 간단한 경우입니다. –

0

재귀 쿼리가 실제로 필요합니까? ') (getactivities'당신은 당신의 의도 된 의미에 대한 세부 사항을 제공하는 데 실패

declare @TableActivity table 
([Type]    VARCHAR(8) 
,Activity   VARCHAR(8) 
,RelatedActivity  VARCHAR(8) 
) 


insert @TableActivity 
     select 'Start','a','-' 
union select 'Transfer','a','b' 
union select 'Start','b','-' 
union select 'Transfer','b','c' 
union select 'Start','c','-' 
union select 'Stop','c','-' 
union select 'Transfer','c','b' 
union select 'Stop','b','-' 
union select 'Transfer','b','a' 
union select 'Stop','a','-' 


select activity 
     ,ROW_NUMBER() OVER (ORDER BY activity) - 1 AS rn 
from @TableActivity 
where [Type] = 'Stop' 
order by 2 
+0

네, 문제를 조금 명확히. – jsw

0

: 당신이 제공 한 샘플 데이터를 바탕으로 필요한 모든 역에서 활동을 중지하는 순서를보고하는 것입니다 맡은 일.

이렇게하면 대답하기가 어려워집니다.

어쨌든 '재귀'에 대해 언급 했으므로 주어진 활동과 관련된 간접적 인 수준의 활동이 포함되도록 결과 집합을 원한다고 가정합니다.

'간접적 인 수준'부분 때문에 재귀를 피할 수 없습니다. 대략 다음과 같이 작동해야합니다.

관련 활동 ('b')을 찾으려면 주어진 활동 세트 ('a')로 시작하십시오. 발견 된 새 활동에서 이미 발견 한 활동을 제거하십시오 (없음). 나머지 집합을 결과 집합에 추가하고이 집합을 사용하여 반복합니다. 주어진 활동 집합 ('b')을 사용하여 관련 작업 ('a' 'c')을 찾습니다. 발견 된 새 활동에서 이미 발견 한 활동 ('a')을 제거하십시오. 나머지 집합 ('c')을 결과 집합에 추가하고이 집합으로 반복합니다. 주어진 활동 집합 ('c')으로 관련 활동 ('b')을 찾습니다. 발견 된 새 활동에서 이미 발견 한 활동을 제거하십시오 ('b'). 나머지 세트 (없음)를 결과 세트에 추가하십시오. 결과 세트가 없으므로 완료되었습니다.

죄송합니다. 나는 이것을 모자 위에 올려 놓을 수 없어서 SQL로 변환 할 수 없습니다.

0

나는 그것을 시도해 봤지만, 그것이 좋을 지 말할 수는 없다. 그렇지 않은 경우 무시하십시오.

WITH TMP AS (
SELECT activity, relatedactivity 
FROM tableactivity root 
WHERE root.activity = 'a' and root.type='transfer' 
UNION ALL 
SELECT next.activity, next.relatedactivity 
FROM tableactivity next, TMP prior 
WHERE prior.relatedactivity = next.activity and next.type='transfer' 
    AND not exists (SELECT * FROM TMP ttmp 
        WHERE ttmp.activity = next.relatedactivity 
        AND ttmp.relatedactivity = next.activity) 
       ) 
) 
SELECT relatedactivity FROM TMP 
UNION (ALL ???) 
SELECT 'a' from <nonemptytable> 

PS 당신의 orderingnumber 경우와

, 즉 그래프와 자신의 폐쇄와 잘 맞지 않는 개념이다. a에서 c까지 길이가 다른 여러 경로가 여러 개인 경우 전화 번호는 무엇입니까? Erwins 입력을 기반으로

+0

예, 주문 번호가 잘 맞지 않습니다. '공통 테이블 표현식의 재귀 멤버'TMP '에 여러 재귀 참조가 있습니다.' 이 쿼리에서 내가 주변을 둘러 볼 수 있는지 알아 내려고. – jsw

+0

NOT EXISTS는 거기에 있어야하지만 CTE의 제약 하에서 그것을 수행 할 방법을 찾아 내지 못합니다. – jsw

관련 문제