根据上一行的值排序SQL查询
我设计了一个数据库,其中存储了执行流程所需的所有信息。所谓“过程”,我指的是一系列的多个步骤,或者换句话说,一个配方。每个配方(在我的例子中是任务)都包含几个步骤。一个给定的步骤可以出现在不同的配方中 以下是我拥有的3个表的示例(随机数据): 过程表根据上一行的值排序SQL查询,sql,sql-server,common-table-expression,Sql,Sql Server,Common Table Expression,我设计了一个数据库,其中存储了执行流程所需的所有信息。所谓“过程”,我指的是一系列的多个步骤,或者换句话说,一个配方。每个配方(在我的例子中是任务)都包含几个步骤。一个给定的步骤可以出现在不同的配方中 以下是我拥有的3个表的示例(随机数据): 过程表 +----+------+------+--------+-----------+ | ID | Task | Step | NextID | StartHere | +----+------+------+--------+-----------
+----+------+------+--------+-----------+
| 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
NextID
=0它可以使用DB游标和动态查询来编写 因此,我们的想法是,为
Process
表打开一个DB游标,其中NextID
为TRUE
在光标内,创建一个动态查询:
NextID
=光标NextID
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
布尔列过滤,对吗?正确。。这是您的父查询或基本查询