我正在尝试找到此表中最小的缺失数字。
+------+--------+
| id | number |
+------+--------+
| 902 | 1 |
| 908 | 2 |
| 1007 | 7 |
| 1189 | 8 |
| 1233 | 12 |
| 1757 | 15 |
+------+--------+
在数字栏中,您可以看到数字之间有几个间隙。我需要得到最小间隙之后的数字。所以在上面的例子中我需要数字 3。因为 2 是间隙后的最小数字。
我会用
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;
这里有很多不同的方法,由于使用窗口函数,现在可能很流行。
;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
这是一个很好的版本,甚至可以在 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;