根据上一行

时间:2017-06-13 21:54:18

标签: sql sql-server common-table-expression

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

以下是我拥有的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 | 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     |
+----+--------------+-----------------+--------+-----------+

如图所示,在 Process 表中,每条记录(行)代表Task和step的组合。遵循配方时,NextID列包含下一个任务步骤组合的ID。 NextID 0标志着任务的结束。 StartHere列是一个布尔值,指定根据任务执行的第一步。

遵循这个逻辑,为了“玩数字游戏”,您需要先打开控制台,然后登录,然后打开游戏,最后享受您的游戏会话。

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

基本上,查询应首先获取StepNameStartHere的行的TRUE,然后获取具有StepName的行的ID }等于前一行的NextID,依此类推。

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

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

欢迎任何暗示帮助!

谢谢

编辑:评论中要求的AS,以下是此类查询的预期结果,如果是为了播放数字'任务:

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

3 个答案:

答案 0 :(得分:2)

使用CTE,以Next 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

答案 1 :(得分:0)

获取NextID需要LEAD or LAG

答案 2 :(得分:0)

可以使用DB Cursor和Dynamic query编写。

所以我的想法是,为Process表打开一个DB Cursor,NextIDTRUE

在Cursor内部,创建一个动态查询:

  1. 首先从Cursor变量中选择值。
  2. 与...联合 - 选择NextID =光标NextID
  3. 的值
  4. 重复2直到NextID = 0
  5. 执行动态查询