根据上一行的值排序SQL查询

根据上一行的值排序SQL查询,sql,sql-server,common-table-expression,Sql,Sql Server,Common Table Expression,我设计了一个数据库,其中存储了执行流程所需的所有信息。所谓“过程”,我指的是一系列的多个步骤,或者换句话说,一个配方。每个配方(在我的例子中是任务)都包含几个步骤。一个给定的步骤可以出现在不同的配方中 以下是我拥有的3个表的示例(随机数据): 过程表 +----+------+------+--------+-----------+ | ID | Task | Step | NextID | StartHere | +----+------+------+--------+-----------

我设计了一个数据库,其中存储了执行流程所需的所有信息。所谓“过程”,我指的是一系列的多个步骤,或者换句话说,一个配方。每个配方(在我的例子中是任务)都包含几个步骤。一个给定的步骤可以出现在不同的配方中

以下是我拥有的3个表的示例(随机数据):

过程表

+----+------+------+--------+-----------+
| ID | Task | Step | NextID | StartHere |
+----+------+------+--------+-----------+
|  1 |    2 |    1 |      4 | TRUE      |
|  2 |    2 |    5 |      8 | FALSE     |
|  3 |    4 |    5 |      9 | FALSE     |
|  4 |    2 |    2 |      2 | FALSE     |
|  5 |    4 |    2 |      6 | FALSE     |
|  6 |    4 |    4 |      3 | FALSE     |
|  7 |    4 |    1 |      5 | TRUE      |
|  8 |    2 |   15 |      0 | FALSE     |
|  9 |    4 |   15 |      0 | FALSE     |
+----+------+------+--------+-----------+
+--------+--------------+
| TaskID |   TaskName   |
+--------+--------------+
|      1 | Buy Disk     |
|      2 | Play Disk    |
|      3 | Buy Digital  |
|      4 | Play Digital |
+--------+--------------+
+--------+-----------------+
| StepID |    StepName     |
+--------+-----------------+
|      1 | Turn Console On |
|      2 | Log In          |
|      4 | Insert Disk     |
|      5 | Open Game       |
|     15 | Enjoy           |
+--------+-----------------+
任务表

+----+------+------+--------+-----------+
| ID | Task | Step | NextID | StartHere |
+----+------+------+--------+-----------+
|  1 |    2 |    1 |      4 | TRUE      |
|  2 |    2 |    5 |      8 | FALSE     |
|  3 |    4 |    5 |      9 | FALSE     |
|  4 |    2 |    2 |      2 | FALSE     |
|  5 |    4 |    2 |      6 | FALSE     |
|  6 |    4 |    4 |      3 | FALSE     |
|  7 |    4 |    1 |      5 | TRUE      |
|  8 |    2 |   15 |      0 | FALSE     |
|  9 |    4 |   15 |      0 | FALSE     |
+----+------+------+--------+-----------+
+--------+--------------+
| TaskID |   TaskName   |
+--------+--------------+
|      1 | Buy Disk     |
|      2 | Play Disk    |
|      3 | Buy Digital  |
|      4 | Play Digital |
+--------+--------------+
+--------+-----------------+
| StepID |    StepName     |
+--------+-----------------+
|      1 | Turn Console On |
|      2 | Log In          |
|      4 | Insert Disk     |
|      5 | Open Game       |
|     15 | Enjoy           |
+--------+-----------------+
步进稳定

+----+------+------+--------+-----------+
| ID | Task | Step | NextID | StartHere |
+----+------+------+--------+-----------+
|  1 |    2 |    1 |      4 | TRUE      |
|  2 |    2 |    5 |      8 | FALSE     |
|  3 |    4 |    5 |      9 | FALSE     |
|  4 |    2 |    2 |      2 | FALSE     |
|  5 |    4 |    2 |      6 | FALSE     |
|  6 |    4 |    4 |      3 | FALSE     |
|  7 |    4 |    1 |      5 | TRUE      |
|  8 |    2 |   15 |      0 | FALSE     |
|  9 |    4 |   15 |      0 | FALSE     |
+----+------+------+--------+-----------+
+--------+--------------+
| TaskID |   TaskName   |
+--------+--------------+
|      1 | Buy Disk     |
|      2 | Play Disk    |
|      3 | Buy Digital  |
|      4 | Play Digital |
+--------+--------------+
+--------+-----------------+
| StepID |    StepName     |
+--------+-----------------+
|      1 | Turn Console On |
|      2 | Log In          |
|      4 | Insert Disk     |
|      5 | Open Game       |
|     15 | Enjoy           |
+--------+-----------------+
下面是上面的流程表,但包含步骤和任务的实际名称。使用此表可能更容易理解:

+----+--------------+-----------------+--------+-----------+
| ID |     Task     |      Step       | NextID | StartHere |
+----+--------------+-----------------+--------+-----------+
|  1 | Play Disk    | Turn Console On |      4 | TRUE      |
|  2 | Play Disk    | Open Game       |      8 | FALSE     |
|  3 | Play Digital | Open Game       |      9 | FALSE     |
|  4 | Play Disk    | Log In          |      2 | FALSE     |
|  5 | Play Digital | Log In          |      6 | FALSE     |
|  6 | Play Digital | Insert Disk     |      3 | FALSE     |
|  7 | Play Digital | Turn Console On |      5 | TRUE      |
|  8 | Play Disk    | Enjoy           |      0 | FALSE     |
|  9 | Play Digital | Enjoy           |      0 | FALSE     |
+----+--------------+-----------------+--------+-----------+
如图所示,在流程表中,每条记录(行)表示任务和步骤的组合。
NextID
列包含遵循配方时下一个任务步骤组合的ID。
0
NextID
标志着任务的结束。
StartHere
列是一个布尔值,根据任务指定要执行的第一步

按照这个逻辑,为了“玩一个数字游戏”,你需要先打开游戏机,然后登录,然后打开游戏,最后享受游戏过程

我的问题是: 我想找到一种方法来查询完成给定任务所需的所有步骤,并按照适当的顺序(根据流程表执行这些步骤的顺序)进行排序。是否有人知道如何做到这一点(如果可能,在一个查询中)

基本上,查询应该首先获取
StartHere
TRUE
的行的
StepName
,然后获取
ID
等于前一行的
NextID
的行的
StepName
,依此类推

我提出了以下查询,但这并没有给出正确的顺序:

SELECT Step.StepName 
FROM Step
    INNER JOIN Process ON Step.StepID = Process.Step
    INNER JOIN Task ON Process.Task = Task.TaskID
WHERE Task.TaskID = 4
ORDER BY Process.NextID
欢迎任何提示的帮助

多谢各位

编辑:根据评论中的要求,以下是此类查询的预期结果(如果是针对“数字播放”任务执行的):

+-----------------+
|    StepNane     |
+-----------------+
| Turn Console On |
| Log In          |
| Open Game       |
| Enjoy           |
+-----------------+

听起来需要获取NextID。

听起来需要获取NextID。

可以使用DB游标和动态查询写入

因此,我们的想法是,为
Process
表打开一个DB游标,其中
NextID
TRUE

在光标内,创建一个动态查询:

  • 首先从游标变量中选择值
  • 与联合-选择
    NextID
    =光标
    NextID
  • 重复2直到下一次
    NextID
    =0
  • 执行动态查询

  • 它可以使用DB游标和动态查询来编写

    因此,我们的想法是,为
    Process
    表打开一个DB游标,其中
    NextID
    TRUE

    在光标内,创建一个动态查询:

  • 首先从游标变量中选择值
  • 与联合-选择
    NextID
    =光标
    NextID
  • 重复2直到下一次
    NextID
    =0
  • 执行动态查询

  • 使用CTE,以下一个id的形式获取子节点原理

    declare @mytable table
    (id int,
    task varchar(50),
    step varchar(50),
    nextid int
    )
    
    
    insert into @mytable
    values 
    (  1 ,'Play Disk    ','Turn Console On ',      4 ),
    (  2 ,'Play Disk   ','Open Game       ',      8 ),
    (  3 ,'Play Digital ','Open Game       ',      9 ),
    (  4 ,'Play Disk    ','Log In          ',      2 ),
    (  5 ,'Play Digital ','Log In          ',     6 ),
    (  6 ,'Play Digital ','Insert Disk     ',     3 ),
    (  7 ,'Play Digital ','Turn Console On ',      5 ),
    (  8 ,'Play Disk    ','Enjoy           ',      0 ),
    (  9 ,'Play Digital ','Enjoy           ',      0 )
    
    
    ;with mycte
    as 
    (
     select * from @mytable  where id = 1 -- to start from this ID, if you want this your START here column with true then eventually you will have multiple outputs
     union all
     select t.* from @mytable t
     inner join mycte c on c.nextid = t.id
     )
    select * from mycte;
    
    结果,从1开始

    id  task            step                nextid
    1   Play Disk       Turn Console On     4
    4   Play Disk       Log In              2
    2   Play Disk       Open Game           8
    8   Play Disk       Enjoy               0
    
    结果,从7开始

    id  task            step                nextid
    7   Play Digital    Turn Console On     5
    5   Play Digital    Log In              6
    6   Play Digital    Insert Disk         3
    3   Play Digital    Open Game           9
    9   Play Digital    Enjoy               0
    

    使用CTE,以下一个id的形式获取子节点原理

    declare @mytable table
    (id int,
    task varchar(50),
    step varchar(50),
    nextid int
    )
    
    
    insert into @mytable
    values 
    (  1 ,'Play Disk    ','Turn Console On ',      4 ),
    (  2 ,'Play Disk   ','Open Game       ',      8 ),
    (  3 ,'Play Digital ','Open Game       ',      9 ),
    (  4 ,'Play Disk    ','Log In          ',      2 ),
    (  5 ,'Play Digital ','Log In          ',     6 ),
    (  6 ,'Play Digital ','Insert Disk     ',     3 ),
    (  7 ,'Play Digital ','Turn Console On ',      5 ),
    (  8 ,'Play Disk    ','Enjoy           ',      0 ),
    (  9 ,'Play Digital ','Enjoy           ',      0 )
    
    
    ;with mycte
    as 
    (
     select * from @mytable  where id = 1 -- to start from this ID, if you want this your START here column with true then eventually you will have multiple outputs
     union all
     select t.* from @mytable t
     inner join mycte c on c.nextid = t.id
     )
    select * from mycte;
    
    结果,从1开始

    id  task            step                nextid
    1   Play Disk       Turn Console On     4
    4   Play Disk       Log In              2
    2   Play Disk       Open Game           8
    8   Play Disk       Enjoy               0
    
    结果,从7开始

    id  task            step                nextid
    7   Play Digital    Turn Console On     5
    5   Play Digital    Log In              6
    6   Play Digital    Insert Disk         3
    3   Play Digital    Open Game           9
    9   Play Digital    Enjoy               0
    


    请张贴预期的result@maSTAShuFu谢谢你的建议。我已将预期结果添加到sql server的Post.version?似乎您只需按任务排序,步骤。还是我遗漏了什么?请将预期的result@maSTAShuFu谢谢你的建议。我已将预期结果添加到sql server的Post.version?似乎您只需按任务排序,步骤。还是我遗漏了什么?谢谢你的建议。这似乎是我需要的。你能举个例子吗?首先不要使用游标,解决办法是CTE获取所有子项,其中子项是下一个数字。我同意,使用游标不是明智的选择。CTE适用于此。谢谢您的想法。这似乎是我需要的。你能举个例子吗?首先不要使用游标,解决办法是CTE获取所有子项,其中子项是下一个数字。我同意,使用游标不是明智的选择。CTE适用于此。非常感谢您!从来没有听说过CTE,但在你发完帖子后,我去做了一些研究,真不敢相信它们有多有用!它打开了一个全新的范围,你可以做的事情!我认为每个人都应该去学习常见的表表达式……如果我理解正确,CTE查询定义中的第一个
    SELECT
    语句应该只返回一行,以便在递归完成后始终得到相同的结果。这就是为什么在
    WHERE
    子句中按
    ID
    过滤,而不是按
    StartHere
    布尔列过滤,对吗?正确。。这是你的父母或基本问题谢谢你!从来没有听说过CTE,但在你发完帖子后,我去做了一些研究,真不敢相信它们有多有用!它打开了一个全新的范围,你可以做的事情!我认为每个人都应该去学习常见的表表达式……如果我理解正确,CTE查询定义中的第一个
    SELECT
    语句应该只返回一行,以便在递归完成后始终得到相同的结果。这就是为什么在
    WHERE
    子句中按
    ID
    过滤,而不是按
    StartHere
    布尔列过滤,对吗?正确。。这是您的父查询或基本查询