SQL查询来查找缺less的序列号

我有一个名为sequence的列。 该列中的数据看起来像1,2,3,4,5,7,9,10,15。

我需要从表中find缺less的序列号。 什么SQL查询将从我的表中find丢失的序列号? 我期待像这样的结果

 Missing numbers --------------- 6 8 11 12 13 14 

我只使用一个表。 我试过下面的查询,但没有得到我想要的结果。

 select de.sequence + 1 as sequence from dataentry as de left outer join dataentry as de1 on de.sequence + 1 = de1.sequence where de1.sequence is null order by sequence asc; 

感觉如何?

  select (select isnull(max(val)+1,1) from mydata where val < md.val) as [from], md.val - 1 as [to] from mydata md where md.val != 1 and not exists ( select 1 from mydata md2 where md2.val = md.val - 1) 

给出总结结果:

 from to ----------- ----------- 6 6 8 8 11 14 

我知道这是一个很老的post,但我想添加这个解决scheme,我发现这里,以便我可以find更容易:

 WITH Missing (missnum, maxid) AS ( SELECT 1 AS missnum, (select max(id) from @TT) UNION ALL SELECT missnum + 1, maxid FROM Missing WHERE missnum < maxid ) SELECT missnum FROM Missing LEFT OUTER JOIN @TT tt on tt.id = Missing.missnum WHERE tt.id is NULL OPTION (MAXRECURSION 0); 

最好的解决scheme是那些使用序列临时表。 假设你build立这样一个表,LEFT JOIN和NULL检查应该做这个工作:

 SELECT #sequence.value FROM #sequence LEFT JOIN MyTable ON #sequence.value = MyTable.value WHERE MyTable.value IS NULL 

但是如果你不得不经常重复这个操作(对于数据库中的一个序列),我会创build一个“静态数据”表,并有一个脚本来填充你需要的所有表的MAX(值) 。

试试这个:

 declare @min int declare @max int select @min = min(seq_field), @max = max(seq_field) from [Table] create table #tmp (Field_No int) while @min <= @max begin if not exists (select * from [Table] where seq_field = @min) insert into #tmp (seq_field) values (@min) set @min = @min + 1 end select * from #tmp drop table #tmp 

这里是一个脚本来创build一个存储过程返回给定的date范围的序列号丢失。

 CREATE PROCEDURE dbo.ddc_RolledBackOrders -- Add the parameters for the stored procedure here @StartDate DATETIME , @EndDate DATETIME AS BEGIN SET NOCOUNT ON; DECLARE @Min BIGINT DECLARE @Max BIGINT DECLARE @i BIGINT IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL BEGIN DROP TABLE #TempTable END CREATE TABLE #TempTable ( TempOrderNumber BIGINT ) SELECT @Min = ( SELECT MIN(ordernumber) FROM dbo.Orders WITH ( NOLOCK ) WHERE OrderDate BETWEEN @StartDate AND @EndDate) SELECT @Max = ( SELECT MAX(ordernumber) FROM dbo.Orders WITH ( NOLOCK ) WHERE OrderDate BETWEEN @StartDate AND @EndDate) SELECT @i = @Min WHILE @i <= @Max BEGIN INSERT INTO #TempTable SELECT @i SELECT @i = @i + 1 END SELECT TempOrderNumber FROM #TempTable LEFT JOIN dbo.orders o WITH ( NOLOCK ) ON tempordernumber = o.OrderNumber WHERE o.OrderNumber IS NULL END 

 SELECT CASE WHEN MAX(column_name) = COUNT(*) THEN CAST(NULL AS INTEGER) -- THEN MAX(column_name) + 1 as other option WHEN MIN(column_name) > 1 THEN 1 WHEN MAX(column_name) <> COUNT(*) THEN (SELECT MIN(column_name)+1 FROM table_name WHERE (column_name+ 1) NOT IN (SELECT column_name FROM table_name)) ELSE NULL END FROM table_name; 

这是我对这个问题的解释,将内容放置在Tablevariables中,我可以在脚本的其余部分轻松访问它。

 DECLARE @IDS TABLE (row int, ID int) INSERT INTO @IDS select ROW_NUMBER() OVER (ORDER BY x.[Referred_ID]), x.[Referred_ID] FROM (SELECT b.[Referred_ID] + 1 [Referred_ID] FROM [catalog].[dbo].[Referrals] b) as x LEFT JOIN [catalog].[dbo].[Referrals] a ON x.[Referred_ID] = a.[Referred_ID] WHERE a.[Referred_ID] IS NULL select * from @IDS 

为了好玩,我决定发布我的解决scheme。
我在表格中有一个身份专栏,我想查找缺less的发票号码。 我回顾了我能find的所有例子,但是它们不够优雅。

 CREATE VIEW EENSkippedInvoicveNo AS SELECT CASE WHEN MSCNT = 1 THEN CAST(MSFIRST AS VARCHAR (8)) ELSE CAST(MSFIRST AS VARCHAR (8)) + ' - ' + CAST(MSlAST AS VARCHAR (8)) END AS MISSING, MSCNT, INV_DT FROM ( select invNo+1 as Msfirst, inv_no -1 as Mslast, inv_no - invno -1 as msCnt, dbo.fmtdt(Inv_dt) AS INV_dT from (select inv_no as invNo, a4glidentity + 1 as a4glid from oehdrhst_sql where inv_dt > 20140401) as s inner Join oehdrhst_sql as h on a4glid = a4glidentity where inv_no - invno <> 1 ) AS SS 
 DECLARE @MaxID INT = (SELECT MAX(timerecordid) FROM dbo.TimeRecord) SELECT SeqID AS MissingSeqID FROM (SELECT ROW_NUMBER() OVER (ORDER BY column_id) SeqID from sys.columns) LkUp LEFT JOIN dbo.TimeRecord t ON t.timeRecordId = LkUp.SeqID WHERE t.timeRecordId is null and SeqID < @MaxID 

我在这里find了这个答案: http : //sql-developers.blogspot.com/2012/10/how-to-find-missing-identitysequence.html

我正在寻找一个解决scheme,并find了很多答案。 这是我用过的,它工作得很好。 我希望这可以帮助任何人寻找类似的答案。

并不是所有的解决scheme都太复杂? 这不是很简单:

 SELECT * FROM (SELECT row_number() over(order by number) as N from master..spt_values) t where N not in (select 1 as sequence union select 2 union select 3 union select 4 union select 5 union select 7 union select 10 union select 15 ) 
 DECLARE @TempSujith TABLE (MissingId int) Declare @Id Int DECLARE @mycur CURSOR SET @mycur = CURSOR FOR Select Id From tbl_Table OPEN @mycur FETCH NEXT FROM @mycur INTO @Id Declare @index int Set @index = 1 WHILE @@FETCH_STATUS = 0 BEGIN if (@index < @Id) begin while @index < @Id begin insert into @TempSujith values (@index) set @index = @index + 1 end end set @index = @index + 1 FETCH NEXT FROM @mycur INTO @Id END Select Id from tbl_Table select MissingId from @TempSujith 

创build一个有用的Tally表 :

 -- can go up to 4 million or 2^22 select top 100000 identity(int, 1, 1) Id into Tally from master..spt_values cross join master..spt_values 

索引它,或者把这个单列作为PK。 然后使用EXCEPT来获取您的缺失号码。

 select Id from Tally where Id <= (select max(Id) from TestTable) except select Id from TestTable 

你也可以使用像CTE这样的东西来解决这个问题:

创build表#tmp(sequence int)

插入到#tmp(sequence)值(1)
插入到#tmp(sequence)值(2)
插入#tmp(sequence)值(3)
插入#tmp(sequence)值(5)
插入#tmp(sequence)值(6)
插入#tmp(sequence)值(8)
插入到#tmp(序列)值(10)
插入#tmp(sequence)值(11)
插入#tmp(序列)值(14)

  DECLARE @max INT SELECT @max = max(sequence) from #tmp; with full_sequence ( Sequence ) as ( SELECT 1 Sequence UNION ALL SELECT Sequence + 1 FROM full_sequence WHERE Sequence < @max ) SELECT full_sequence.sequence FROM full_sequence LEFT JOIN #tmp ON full_sequence.sequence = #tmp.sequence WHERE #tmp.sequence IS NULL 

嗯 – 由于某种原因,格式不适用于此? 任何人都可以看到问题?

http://www.duelec.de/blog/?p=337上有一个关于SQL的讨论来解决这类问题。;

它不是专门在sqlserver2005中编写的,但它应该给你足够的信息来适应它。