0

具有以下结构和示例数据的表:

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 查询来完成以下任务:

GetActivities('a')

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

我很难编写一个停止在递归语句中返回行的语句。

有任何想法吗?

编辑

澄清 GetActivities('a')。此函数应找到“a”的“开始”活动并继续查找“a”上的任何“转移”活动。此时,该函数可以使用“b”递归,从而使用样本数据递归“c”。查询应通过“Transfers”返回与“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
 }
4

4 回答 4

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
于 2009-11-06T21:27:42.820 回答
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
于 2009-11-06T08:33:45.140 回答
0

您未能提供有关“getactivities()”事物的预期语义的任何详细信息。

这使得这个问题很难回答。

但无论如何,由于您提到了“递归”,我假设您希望结果集包含与给定活动相关的任何间接级别的任何活动。

由于“在任何间接级别”部分,您无法避免递归。它应该大致如下操作:

从给定的活动集 ('a') 开始以查找相关活动 ('b')。从找到的新活动中,删除您已经找到的活动(无)。将其余的添加到结果集中并使用此集重复:使用给定的活动集('b'),找到相关的活动('a''c')。从找到的新活动中,删除您已经找到的活动 ('a')。将剩余的('c')添加到结果集中并重复此集:使用给定的活动集('c'),找到相关的活动('b')。从找到的新活动中,删除您已经找到的活动 ('b')。将剩余的(无)添加到结果集中,因为没有,所以你完成了。

抱歉,我无法将其转换为 SQL。

于 2009-11-06T17:16:36.723 回答
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>

附言

至于你的orderingnumber,这是一个不太适合图表及其闭包的概念。如果从 a 到 c 有多个不同长度的不同路径,你希望你的数字是多少?

于 2009-11-06T19:13:50.703 回答