【问题标题】:How to find gaps in a sequence of numbers in SQL Server如何在 SQL Server 中查找数字序列中的空白
【发布时间】:2016-07-24 00:22:05
【问题描述】:

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

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

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

【问题讨论】:

  • 您只需要数字还是整行?

标签: sql sql-server sql-server-2014


【解决方案1】:

我会使用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;

如果您想确保 id 从 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;

【讨论】:

    【解决方案2】:

    由于使用了窗口函数,这里有很多不同的方式,这可能是当今流行的一种方式。

    ;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

    【讨论】:

    • 但只有最后一个返回正确的数字,在我的应用程序中
    • @Joe 很抱歉您无法在您的应用程序中实现此功能,但我添加了一个指向 rextester 的链接,显示所有 3 个功能正常,如果您有需要的特定问题,则返回 3 个帮助不要犹豫发布问题并联系我,我会看看它。
    【解决方案3】:

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

    Demo Here

    ;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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-12
      • 2020-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多