Sql server 行号需要递归/循环查询帮助
我希望能够追溯材料、用于移动的设备和计时的移动表,从字段中的指定值开始,并根据共享值在不同行的另一个字段中查找该值 在下表中,我需要能够追溯到,例如,从端码“M”所有相关行,一直追溯到StartCode A。然后,我可能希望能够追溯到从端码“U”到StartCode“N”的所有行 在表中,起始代码(物料)A和B被移动为末端代码C。末端代码C随后成为起始代码,然后与起始代码E一起移动为末端代码F等。橙色/蓝色行表示物料移动组 由此,我想创建一个新的表/视图,它在下一个事件发生时将StartedAt作为一个名为“EndedAt”的新字段引入。它将如下所示: 我创建了一个递归查询,它使用ROW_NUMBER和CTE将StartedAt作为一个新字段“EndedAt”传入 然后,我尝试使用一个嵌套的SELECT语句来查找与EndCode“M”相关的所有StartCodes,试图在表中循环搜索StartCode列中的所有相关EndCodes。这只带来了几行。我将嵌套语句重复几次,使其穿过不同的行 我需要帮助来获取创建所需表/视图所需的所有相关开始/结束代码 最终,一份报告将附在表格上,允许表格通过所选的端码参数(如M、U等)进行过滤Sql server 行号需要递归/循环查询帮助,sql-server,loops,recursive-query,row-number,ssms-2017,Sql Server,Loops,Recursive Query,Row Number,Ssms 2017,我希望能够追溯材料、用于移动的设备和计时的移动表,从字段中的指定值开始,并根据共享值在不同行的另一个字段中查找该值 在下表中,我需要能够追溯到,例如,从端码“M”所有相关行,一直追溯到StartCode A。然后,我可能希望能够追溯到从端码“U”到StartCode“N”的所有行 在表中,起始代码(物料)A和B被移动为末端代码C。末端代码C随后成为起始代码,然后与起始代码E一起移动为末端代码F等。橙色/蓝色行表示物料移动组 由此,我想创建一个新的表/视图,它在下一个事件发生时将StartedAt
EndedAt
是一个简单的连接:
SELECT
S.StartCode,
S.StartedAt,
S.EndCode,
E.StartedAt AS EndedAt
FROM
MyTable AS S
LEFT JOIN MyTable AS E ON S.EndCode = E.StartCode
结果:
StartCode StartedAt EndCode EndedAt
A 2019-01-01 01:00:00.000 C 2019-01-01 03:00:00.000
B 2019-01-01 02:15:00.000 C 2019-01-01 03:00:00.000
C 2019-01-01 03:00:00.000 F 2019-01-01 04:14:00.000
D 2019-01-01 03:19:00.000 F 2019-01-01 04:14:00.000
E 2019-01-01 04:00:00.000 F 2019-01-01 04:14:00.000
F 2019-01-01 04:14:00.000 G 2019-01-01 05:00:00.000
G 2019-01-01 05:00:00.000 J 2019-01-01 06:00:00.000
H 2019-01-01 05:37:00.000 J 2019-01-01 06:00:00.000
I 2019-01-01 05:45:00.000 J 2019-01-01 06:00:00.000
J 2019-01-01 06:00:00.000 L 2019-01-01 07:00:00.000
K 2019-01-01 06:09:00.000 L 2019-01-01 07:00:00.000
L 2019-01-01 07:00:00.000 M NULL
N 2019-01-01 09:20:00.000 P 2019-01-01 09:45:00.000
O 2019-01-01 09:37:00.000 P 2019-01-01 09:45:00.000
P 2019-01-01 09:45:00.000 Q 2019-01-01 11:00:00.000
Q 2019-01-01 11:00:00.000 T 2019-01-01 11:58:00.000
R 2019-01-01 11:10:00.000 T 2019-01-01 11:58:00.000
S 2019-01-01 11:47:00.000 T 2019-01-01 11:58:00.000
T 2019-01-01 11:58:00.000 U NULL
CurrentCode CurrentStartAt LastCode EndedAt PreviousCode RecursionLevel RecursionPath
A 2019-01-01 01:00:00.000 J 2019-01-01 06:00:00.000 C 4 J->G->F->C->A
B 2019-01-01 02:15:00.000 J 2019-01-01 06:00:00.000 C 4 J->G->F->C->B
C 2019-01-01 03:00:00.000 J 2019-01-01 06:00:00.000 F 3 J->G->F->C
D 2019-01-01 03:19:00.000 J 2019-01-01 06:00:00.000 F 3 J->G->F->D
E 2019-01-01 04:00:00.000 J 2019-01-01 06:00:00.000 F 3 J->G->F->E
F 2019-01-01 04:14:00.000 J 2019-01-01 06:00:00.000 G 2 J->G->F
G 2019-01-01 05:00:00.000 J 2019-01-01 06:00:00.000 J 1 J->G
H 2019-01-01 05:37:00.000 J 2019-01-01 06:00:00.000 J 1 J->H
I 2019-01-01 05:45:00.000 J 2019-01-01 06:00:00.000 J 1 J->I
您可以使用以下方法显示层次结构(在本例中,使用自底向上的递归CTE方法)。首先确保数据中没有循环
编辑:如果您想检查层次结构中的任何步骤以及向上的步骤,锚定需要是任何代码(不仅仅是最后一个M
或U
),因此我删除了锚定中的WHERE
DECLARE @EndCodeFilter CHAR(1) = 'J'
;WITH RecursiveCodes AS
(
-- Anchor
SELECT
LastCode = M.EndCode,
CurrentCode = M.StartCode,
PreviousCode = M.EndCode,
RecursionLevel = 1,
RecursionPath = CONVERT(NVARCHAR(MAX), M.EndCode + '->' + M.StartCode),
CurrentStartAt = M.StartedAt
FROM
MyTable AS M
UNION ALL
-- Recursion: link related codes
SELECT
LastCode = R.LastCode,
CurrentCode = M.StartCode,
PreviousCode = M.EndCode,
RecursionLevel = R.RecursionLevel + 1,
RecursionPath = R.RecursionPath + '->' + M.StartCode,
CurrentStartAt = M.StartedAt
FROM
RecursiveCodes AS R
INNER JOIN MyTable AS M ON R.CurrentCode = M.EndCode
)
SELECT
R.CurrentCode,
R.CurrentStartAt,
R.LastCode,
EndedAt = E.StartedAt,
R.PreviousCode,
R.RecursionLevel,
R.RecursionPath
FROM
RecursiveCodes AS R
LEFT JOIN MyTable AS E ON R.LastCode = E.StartCode
WHERE
R.LastCode = @EndCodeFilter
ORDER BY
R.CurrentCode,
R.LastCode
OPTION
(MAXRECURSION 0)
结果:
StartCode StartedAt EndCode EndedAt
A 2019-01-01 01:00:00.000 C 2019-01-01 03:00:00.000
B 2019-01-01 02:15:00.000 C 2019-01-01 03:00:00.000
C 2019-01-01 03:00:00.000 F 2019-01-01 04:14:00.000
D 2019-01-01 03:19:00.000 F 2019-01-01 04:14:00.000
E 2019-01-01 04:00:00.000 F 2019-01-01 04:14:00.000
F 2019-01-01 04:14:00.000 G 2019-01-01 05:00:00.000
G 2019-01-01 05:00:00.000 J 2019-01-01 06:00:00.000
H 2019-01-01 05:37:00.000 J 2019-01-01 06:00:00.000
I 2019-01-01 05:45:00.000 J 2019-01-01 06:00:00.000
J 2019-01-01 06:00:00.000 L 2019-01-01 07:00:00.000
K 2019-01-01 06:09:00.000 L 2019-01-01 07:00:00.000
L 2019-01-01 07:00:00.000 M NULL
N 2019-01-01 09:20:00.000 P 2019-01-01 09:45:00.000
O 2019-01-01 09:37:00.000 P 2019-01-01 09:45:00.000
P 2019-01-01 09:45:00.000 Q 2019-01-01 11:00:00.000
Q 2019-01-01 11:00:00.000 T 2019-01-01 11:58:00.000
R 2019-01-01 11:10:00.000 T 2019-01-01 11:58:00.000
S 2019-01-01 11:47:00.000 T 2019-01-01 11:58:00.000
T 2019-01-01 11:58:00.000 U NULL
CurrentCode CurrentStartAt LastCode EndedAt PreviousCode RecursionLevel RecursionPath
A 2019-01-01 01:00:00.000 J 2019-01-01 06:00:00.000 C 4 J->G->F->C->A
B 2019-01-01 02:15:00.000 J 2019-01-01 06:00:00.000 C 4 J->G->F->C->B
C 2019-01-01 03:00:00.000 J 2019-01-01 06:00:00.000 F 3 J->G->F->C
D 2019-01-01 03:19:00.000 J 2019-01-01 06:00:00.000 F 3 J->G->F->D
E 2019-01-01 04:00:00.000 J 2019-01-01 06:00:00.000 F 3 J->G->F->E
F 2019-01-01 04:14:00.000 J 2019-01-01 06:00:00.000 G 2 J->G->F
G 2019-01-01 05:00:00.000 J 2019-01-01 06:00:00.000 J 1 J->G
H 2019-01-01 05:37:00.000 J 2019-01-01 06:00:00.000 J 1 J->H
I 2019-01-01 05:45:00.000 J 2019-01-01 06:00:00.000 J 1 J->I
最好以
格式化文本
的形式提供示例数据,或者更好地以sql FIDLE的形式提供示例数据。EndedAt列是一个简单而直接的连接(不需要递归或CTE)。对于M到A,如果您能发布完整的DML和DDL示例,我可以帮助您。同时删除bucket列,因为它们对您的问题不重要。请从层次关系中指定您想要的确切输出。好的,使用SL FIDLE,请参阅编辑。谢谢:)我试试看。谢谢,埃兹洛。我能看到的唯一问题是,如果根据我在初始帖子中的示例,我只想,例如,追溯链接到EndCode M和EndCode的所有开始/结束代码,并显示第一组结果中列出的信息。唯一的方法是按照Stat/endcode从字母M返回到A,这是我不能用你(非常感谢)的帮助做到的?层次结构代码可以工作,必须将转换部分更改为NVARCHAR而不是VARCHAR,它工作了。我只需要能够像第一次输出中那样显示一个表,我可以说“只显示与EndCode M相关的行”。我想使用一个@parameter,使用EndCode字段作为值进行选择。@Jimbo我已经编辑了按参数查询的答案。谢谢所有帮助,@EnZo。问题是每一行的EndedAt应该是下一行的StartedAt值,目前它只为每一行提供最后一个StartedAt日期。另外,如果您将参数字母J更改为字母M或U,则EndedAt值都为空。@Jimbo我相信您现在可以编辑查询以满足您的需要。而且M和U没有时间戳,所以你永远也不会知道他们的结束日期。