0

С таблицей следующей структуры и выборки данных:TSQL СТЕ и График Сорта

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    - 

было бы возможно написать запрос КТР выполнить следующее:

GetActivities('a') 

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

I «Мне тяжело писать то, что перестает возвращать строки в рекурсивном выражении.

Любые идеи?

Редактировать

Для уточнения GetActivities ('A'). Эта функция должна найти действие «Старт» «a» и продолжить поиск каких-либо действий «Передача» на «a». В этом случае функция может затем возвращаться с помощью «b» и, следовательно, «c» с данными выборки. Запрос должен возвращать все действия, связанные с 'a' через 'Transfers'. Это вложение деятельности может идти настолько глубоко, насколько это необходимо, и неизвестно (поэтому нет союзов). Трудность, с которой я сталкиваюсь, заключается в том, что есть еще один «Передача», например, '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

на основе ввода Erwins:

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

Действительно ли требуется рекурсивный запрос? На основе выборочных данных, которую вы предоставили, все, что необходимо, чтобы сообщить порядок, что деятельность остановки, в обратном направлении:

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

Вы не смогли дать никаких сведений о предполагаемых семантике вашего «getactivities()» вещь.

Это затрудняет ответ.

Но так или иначе, поскольку вы упомянули «рекурсию», я предполагаю, что вы хотите, чтобы результирующий набор включал любое действие, которое находится на любом уровне косвенности, относящемся к данному действию.

Вы не можете избежать рекурсии из-за части «на любом уровне косвенности». Он должен примерно действовать следующим образом:

Начните с заданного набора действий ('a'), чтобы найти связанные действия ('b'). Из найденных новых действий удалите те, которые вы уже нашли (нет). Добавьте оставшиеся в результирующий набор и повторите с этим набором: С заданным набором действий ('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?

+0

Да, номер заказа не подходит. Я получаю «Рекурсивный член общего табличного выражения« TMP »имеет несколько рекурсивных ссылок. в этом запросе. Попытка выяснить, смогу ли я обойти это. – jsw

+0

Это НЕ СУЩЕСТВУЕТ, должно быть, но я не могу понять, как это сделать при ограничениях CTE. – jsw