【问题标题】:TSQL CTE and a Graph of SortsTSQL CTE 和排序图
【发布时间】:2010-12-13 14:20:13
【问题描述】:

带有如下结构的表格和样本数据:

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
 }

【问题讨论】:

    标签: sql-server tsql hierarchical-data common-table-expression


    【解决方案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 '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
    

    【讨论】:

    • 是的,我稍微澄清了这个问题。
    【解决方案2】:

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

    这使问题难以回答。

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

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

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

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

    【讨论】:

      【解决方案3】:

      我试过了,但不能告诉你它是否有任何好处。如果不是,请忽略。

      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 有多个不同长度的不同路径,你希望你的数字是多少?

      【讨论】:

      • 是的,订货号不太合适。我得到一个“公用表表达式‘TMP’的递归成员有多个递归引用。”在这个查询中。试图弄清楚我是否可以绕过它。
      • That NOT EXISTS 必须在那里,但我无法在 CTE 的约束下找到一种方法。
      【解决方案4】:

      基于欧文输入:

       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
      

      【讨论】:

      • 不会处理更大的周期。在您的示例中添加“UNION SELECT 'Transfer', 'c', 'a'”。
      • 幸运的是,这种情况不会在我的应用程序中发生:活动遍历表现为堆栈。
      • 啊。这比处理具有循环的一般有向图要简单得多。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 2013-02-22
      • 2010-10-08
      相关资源
      最近更新 更多