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中编写的,但它应该给你足够的信息来适应它。