如何在 SQL Server 中查找数字序列中的间隙

问题描述 投票:0回答:4

我正在尝试找到此表中最小的缺失数字。

+------+--------+
| id   | number |
+------+--------+
|  902 |    1   |
|  908 |    2   |
| 1007 |    7   |
| 1189 |    8   |
| 1233 |   12   |
| 1757 |   15   |
+------+--------+

在数字栏中,您可以看到数字之间有几个间隙。我需要得到最小间隙之后的数字。所以在上面的例子中我需要数字 3。因为 2 是间隙后的最小数字。

sql sql-server sql-server-2014
4个回答
5
投票

我会用

lead()

select min(id) + 1
from (select t.*,
             lead(id) over (order by id) as next_id
      from t
     ) t
where next_id <> id + 1;

如果你想确保 ids 从 1 开始(因此如果缺少“1”,则返回该值),你可以这样做:

select (case when min(minid) <> 1 then 1 else min(id) + 1 end)
from (select t.*, min(id) over () as minid
             lead(id) over (order by id) as next_id
      from t
     ) t
where next_id <> id + 1;

4
投票

这里有很多不同的方法,由于使用窗口函数,现在可能很流行。

;WITH cte AS (
    SELECT
       Id
       ,[Number]
       ,LAG([Number],1,NULL) OVER (ORDER BY [Number] ASC) AS LagValue
    FROM
       @Table
)

SELECT
    MIN(LagValue) + 1 AS SmallestNumberAfterGap
FROM
    cte
WHERE
    LagValue <> [Number] - 1

这是一个使用

LEFT JOIN

的总体代码较少的代码
SELECT
    MIN(t2.[Number]) + 1 AS SmallestNumberAfterGap
FROM
    @Table t1
    LEFT JOIN @Table t2
    ON t1.Number + 1 = t2.Number

因为我只是在这里编写更多代码,所以使用的是

EXISTS

SELECT
    MIN(t1.Number) + 1 AS SmallestNumberAfterGap
FROM
    @Table t1
WHERE
    NOT EXISTS (SELECT * FROM @Table t2 WHERE t1.Number + 1 = t2.Number)

这是一个显示所有 3 个选项功能的链接 http://rextester.com/TIFRI87282


0
投票

这个解决方案将为您提供序列中缺失的最小数字,而不是单个数字.. 这使用了数字表..

演示在这里

;With cte
as
(
select 
*
from 
Numbers n
left join
#t1
on n.Number=#t1.num
where n.Number<=(select max(num) from #t1)

)
select 
number from cte c1
join
#t1
on #t1.num+1=c1.Number
where c1.num is null

0
投票

这是一个很好的版本,甚至可以在 SQL2008 中运行!确保 ID 字段已建立索引!它返回缺失记录的数量(gapSize)和缺失记录的范围(gapRange)

通过在 CTE 部分添加 t1 字段,可以轻松地使用附加信息(例如时间戳)进行扩展。

with CTE_NextID as (

    select 
          t1.ID
        , (select top 1 t2.ID from @table t2 where t2.ID > t1.ID order by t2.ID asc) as NextID
    from @table t1

)
select 
      ID
    , NextID
    , cast(ID +1 as varchar(32))+' - '+cast(NextID-1 as varchar(32)) as gapRange
    , nextID - ID - 1 as gapSize
from CTE_NextID 
where NextID > ID + 1
order by ID asc;
© www.soinside.com 2019 - 2024. All rights reserved.