Sql 获取前一行的ID,该行在相关行之前并不总是静态行数?

Sql 获取前一行的ID,该行在相关行之前并不总是静态行数?,sql,database,tsql,hierarchy,lag,Sql,Database,Tsql,Hierarchy,Lag,我知道我的问题听起来很笼统,但如果不写一段话,我就无法详细说明标题中的所有细节。在这里我会尽量直截了当 我有一个表格/订购表格项目的数据库表。每个表单项都可以缩进到某个“级别”。例如,缩进级别IL=0的所有行都是该表单上的顶级项。如果IL=1,并且直接位于IL=0行之后,则IL1行的父行将是前一个IL0行。但是,可以有X个IL1项,它们的父项都是相同的前一个IL0。这种模式可以延续到6个嵌套级别,其中IL6的父级将是以前的IL5 下面是一个表单示例,由我手动填写正确的ParentItemID这是

我知道我的问题听起来很笼统,但如果不写一段话,我就无法详细说明标题中的所有细节。在这里我会尽量直截了当

我有一个表格/订购表格项目的数据库表。每个表单项都可以缩进到某个“级别”。例如,缩进级别IL=0的所有行都是该表单上的顶级项。如果IL=1,并且直接位于IL=0行之后,则IL1行的父行将是前一个IL0行。但是,可以有X个IL1项,它们的父项都是相同的前一个IL0。这种模式可以延续到6个嵌套级别,其中IL6的父级将是以前的IL5

下面是一个表单示例,由我手动填写正确的ParentItemID这是我尝试动态计算的列:

ItemID     FormID     SortOrder     Indent     Description          ParentItemID
1000       1          1             0          Main Item 1          NULL
1001       1          2             0          Main Item 2          NULL
1002       1          3             1          Sub Item 1           1001
1003       1          4             1          Sub Item 2           1001     
1004       1          5             2          Sub Item 2-1         1003
1005       1          6             2          Sub Item 2-2         1003
1006       1          7             2          Sub Item 2-3         1003
1007       1          8             3          Sub Item 2-3-1       1006
1008       1          9             1          Sub Item 3           1001
1009       1          10            0          Main Item 3          NULL
以下是将db中的原始数据转换为表单时的实际情况,仅作为一个可视示例:

我试图使用LAG,它在第一个IL1项上起作用,但是从那里开始,下面的每个项都引用了前一行。我想我可以运行一系列更新,只过滤到每个缩进级别,但这并不理想。我看到滞后需要一个偏移量参数,但由于某种原因,我无法理解如何根据排序顺序动态计算滞后量,以始终引用前一项,该排序顺序的缩进级别比当前缩进级别小1

以下是创建表并填充数据的sql:

create table FormItems(
    ItemID int,     
    FormID int,
    SortOrder int,
    Indent int,
    Description nvarchar(100),
    ParentItemID int
    )

insert into FormItems
select 1000,       1,          1 ,            0,          'Main Item 1'          ,NULL union
select 1001,       1,          2 ,            0,          'Main Item 2'          ,NULL union
select 1002,       1,          3 ,            1,          'Sub Item 1'           ,1001 union
select 1003,       1,          4 ,            1,          'Sub Item 2'           ,1001 union     
select 1004,       1,          5 ,            2,          'Sub Item 2-1'         ,1003 union
select 1005,       1,          6 ,            2,          'Sub Item 2-2'         ,1003 union
select 1006,       1,          7 ,            2,          'Sub Item 2-3'         ,1003 union
select 1007,       1,          8 ,            3,          'Sub Item 2-3-1'       ,1006 union
select 1008,       1,          9 ,            1,          'Sub Item 3'           ,1001 union
select 1009,       1,          10,            0,          'Main Item 3'          ,NULL

最简单的方法可能是:

select t.*, tp.itemId
from t outer apply
     (select top (1) tp.*
      from t tp
      where tp.formId = t.formId and
            tp.indent = t.indent - 1 and
            tp.sortorder < t.sortorder
      order by tp.sortorder desc
     ) tp;