Sql 组内重复序列中缺少间隙

Sql 组内重复序列中缺少间隙,sql,tsql,Sql,Tsql,我们有一个包含以下数据的表 Id,ItemId,SeqNumber;DateTimeTrx 1,100,254,2011-12-01 09:00:00 2,100,1,2011-12-01 09:10:00 3,200,7,2011-12-02 11:00:00 4,200,5,2011-12-02 10:00:00 5,100,255,2011-12-01 09:05:00 6,200,3,2011-12-02 09:00:00 7,300,0,2011-12-03 10:00:00 8,30

我们有一个包含以下数据的表

Id,ItemId,SeqNumber;DateTimeTrx
1,100,254,2011-12-01 09:00:00
2,100,1,2011-12-01 09:10:00
3,200,7,2011-12-02 11:00:00
4,200,5,2011-12-02 10:00:00
5,100,255,2011-12-01 09:05:00
6,200,3,2011-12-02 09:00:00
7,300,0,2011-12-03 10:00:00
8,300,255,2011-12-03 11:00:00
9,300,1,2011-12-03 10:30:00
Id是一个标识列。 ItemId的顺序从0开始,一直到255,然后重置为0。所有这些信息都存储在一个名为Item的表中。序列号的顺序由DateTimeTrx确定,但此类数据可以随时输入系统。预期输出如下所示-

ItemId,PrevorNext,SeqNumber,DateTimeTrx,MissingNumber
100,Previous,255,2011-12-01 09:05:00,0
100,Next,1,2011-12-01 09:10:00,0
200,Previous,3,2011-12-02 09:00:00,4
200,Next,5,2011-12-02 10:00:00,4
200,Previous,5,2011-12-02 10:00:00,6
200,Next,7,2011-12-02 11:00:00,6
300,Previous,1,2011-12-03 10:30:00,2
300,Next,255,2011-12-03 16:30:00,2
我们需要在缺失序列之前和之后分别获取这些行。在上面的ItemId 300示例中,序列为1的记录首先输入了2011-12-03 10:30:00,然后输入了2552011-12-03 16:30:00,因此此处缺少的数字是2。所以1是前一个,255是下一个,2是第一个缺失的数字。对于ItemId 100,序列为255的记录首先输入了2011-12-02 09:05:00,然后输入了1 2011-12-02 09:10:00,因此255是前一个,然后是1,因此0是第一个缺失的数字

在上面的预期结果中,MissingNumber列是第一个出现的MissingNumber,只是为了说明示例

我们不会出现一次完成系列重置的情况,即,它可以是itemid 100中从255到0的系列细分,也可以是itemid 300中从0到255的系列细分。因此,我们需要在升序为0,1,…255或降序为254254,0,2等时识别缺失的序列

我们如何在t-sql中实现这一点?

可以这样工作:

;WITH b AS (
   SELECT *
         ,row_number() OVER (ORDER BY ItemId, DateTimeTrx, SeqNumber) AS rn
   FROM   tbl
   ), x AS (
   SELECT
       b.Id
      ,b.ItemId    AS prev_Itm
      ,b.SeqNumber AS prev_Seq
      ,c.ItemId    AS next_Itm
      ,c.SeqNumber AS next_Seq
   FROM   b
   JOIN   b c ON c.rn = b.rn + 1                -- next row
   WHERE  c.ItemId = b.ItemId                   -- only with same ItemId
   AND    c.SeqNumber <> (b.SeqNumber + 1)%256  -- Seq cycles modulo 256
   )
SELECT Id, prev_Itm, 'Previous' AS PrevNext, prev_Seq
FROM   x
UNION  ALL
SELECT Id, next_Itm ,'Next', next_Seq
FROM   x
ORDER  BY Id, PrevNext DESC
精确地生成请求的结果。 见a

此解决方案考虑了Id列中的间隙,因为问题中没有提到Id的无间隙序列

编辑2:更新问题的答案: 我在上面的查询中更新了CTE,以匹配您的最新版本-或者我认为是这样

使用定义行序列的列。根据需要在ORDERBY子句中添加尽可能多的列以断开连接


对你的最新更新的解释我并不完全清楚,但我认为你只需要挤出DateTimeTrx来实现你想要的。我在ORDER BY中添加了SeqNumber,以打破相同DateTimeTrx留下的联系。我编辑了上面的查询。

为什么结果中的行100,Previous,255和100,Next,1?SeqNumber 255和1之间没有缺少行。您应该使用100,Previous,1和100,Next,3代替??它们在结果中,因为给定项的seqnumber在255到0后重置。在本例中,0丢失,因此255和1都显示为结果。SeqNumber 3用于另一个itemid,它是200,并且该项的缺失序列必须在其集合中单独计算。好的,我知道了。你的成绩很好。发布了匹配的解决方案。请避免重新发布您的问题。改为编辑原稿。最后一部分我不清楚:或者按降序254254,0,2等等。这很完美。谢谢你,欧文。好奇的是,从你的第二次CTE开始,我们是否可以不旋转/应用另一个交叉连接并获得结果?坦率地说,我不知道这是否可行,只是说说而已。实际上,我还有几列将从其他一些表中获得,我只是想知道UNION ALL有什么效果。@VKarthik:UNION ALL是安全的。支点当然是可能的。对于PrevNext和use CASE语句,也可以使用包含两行的表变量进行交叉连接。但我认为提出的解决方案更快、更简单。一个微小的变化:加入而不是左加入-左是不需要的&在这种情况下无效。欧文,我现在遇到了一个问题。实际上,我们得到的记录并不是完全按顺序排列的,两个序列号之间的间隔可能不止一个。在这种情况下,发布的查询失败。我尝试过更改排序子句,但它没有被过滤。你能告诉我哪里出了问题吗?@VKarthik:你的描述不清楚。记录不按顺序排列,间隙可能不止一个。。这些陈述不是决定性的。主键列Id中的间隙对我的查询没有影响,只要Id严格按照升序排列。我建议您编辑您的问题或发布一个包含所有必要数据的新问题,以明确您的案例。我现在已修改了输入数据。我刚才说的是,一个项目的序列号顺序不完全符合顺序,当我执行时,它忽略了先前错过的序列。有什么建议吗?