SQL查询查找丢失的序列号

发布于 2024-07-26 03:01:39 字数 475 浏览 8 评论 0原文

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

我需要从表中找到丢失的序列号。 什么 SQL 查询可以从我的表中找到丢失的序列号? 我期待的结果就像

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;

I have a column named sequence. The data in this column looks like 1, 2, 3, 4, 5, 7, 9, 10, 15.

I need to find the missing sequence numbers from the table. What SQL query will find the missing sequence numbers from my table? I am expecting results like

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

I am using only one table. I tried the query below, but am not getting the results I want.

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

偏爱你一生 2024-08-02 03:01:40
SELECT TOP 1 (Id + 1)
FROM CustomerNumberGenerator
WHERE (Id + 1) NOT IN ( SELECT Id FROM CustomerNumberGenerator )

为我的公司开发客户编号生成器。 不是最有效的,但绝对是最可读的

该表有一个 Id 列。
该表允许用户手动插入 ID 序列。
该解决方案解决了用户决定选择较大数字的情况

SELECT TOP 1 (Id + 1)
FROM CustomerNumberGenerator
WHERE (Id + 1) NOT IN ( SELECT Id FROM CustomerNumberGenerator )

Working on a customer number generator for my company. Not the most efficient but definitely most readable

The table has one Id column.
The table allows for Ids to be inserted at manually by a user off sequence.
The solution solves the case where the user decided to pick a high number

不必了 2024-08-02 03:01:39

怎么样:

  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

How about something like:

  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)

giving summarised results:

from        to
----------- -----------
6           6
8           8
11          14
残疾 2024-08-02 03:01:39

我知道这是一篇非常旧的帖子,但我想添加我发现的这个解决方案 这里这样我可以更容易地找到它:

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); 

I know this is a very old post but I wanted to add this solution that I found HERE so that I can find it easier:

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); 
秋心╮凉 2024-08-02 03:01:39

尝试用这个:

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 (Field_No) values (@min)
   set @min = @min + 1
end
select * from #tmp
drop table #tmp

Try with this:

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 (Field_No) values (@min)
   set @min = @min + 1
end
select * from #tmp
drop table #tmp
我ぃ本無心為│何有愛 2024-08-02 03:01:39

最好的解决方案是使用带有序列的临时表。 假设您构建这样一个表,带有 NULL 检查的 LEFT JOIN 应该可以完成这项工作:

    SELECT      #sequence.value
    FROM        #sequence
    LEFT JOIN   MyTable ON #sequence.value = MyTable.value
    WHERE       MyTable.value IS NULL
            AND #sequence.value < (SELECT MAX(MyTable.value) as max_value FROM MyTable)

但是如果您必须经常重复此操作(并且对于数据库中的 1 个序列更多),我将创建一个“静态数据”表并具有将其填充到您需要的所有表的 MAX(值)的脚本。

The best solutions are those that use a temporary table with the sequence. Assuming you build such a table, LEFT JOIN with NULL check should do the job:

    SELECT      #sequence.value
    FROM        #sequence
    LEFT JOIN   MyTable ON #sequence.value = MyTable.value
    WHERE       MyTable.value IS NULL
            AND #sequence.value < (SELECT MAX(MyTable.value) as max_value FROM MyTable)

But if you have to repeat this operation often (and more then for 1 sequence in the database), I would create a "static-data" table and have a script to populate it to the MAX(value) of all the tables you need.

围归者 2024-08-02 03:01:39
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;
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;
遮了一弯 2024-08-02 03:01:39

下面是一个用于创建存储过程的脚本,该存储过程返回给定日期范围内缺失的序列号。

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

Here is a script to create a stored procedure that returns missing sequential numbers for a given date range.

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

GO

枕梦 2024-08-02 03:01:39
 -- This will return better Results
    -- ----------------------------------
    ;With CTERange
    As (
    select (select isnull(max(ArchiveID)+1,1) from tblArchives where ArchiveID < md.ArchiveID) as [from],
         md.ArchiveID - 1 as [to]
      from tblArchives md
      where md.ArchiveID != 1 and not exists (
            select 1 from tblArchives md2 where md2.ArchiveID = md.ArchiveID - 1)
    ) SELECT [from], [to], ([to]-[from])+1 [total missing]
    From CTERange 
    ORDER BY ([to]-[from])+1 DESC;


from     to     total missing
------- ------- --------------
6        6      1 
8        8      1
11       14     4
 -- This will return better Results
    -- ----------------------------------
    ;With CTERange
    As (
    select (select isnull(max(ArchiveID)+1,1) from tblArchives where ArchiveID < md.ArchiveID) as [from],
         md.ArchiveID - 1 as [to]
      from tblArchives md
      where md.ArchiveID != 1 and not exists (
            select 1 from tblArchives md2 where md2.ArchiveID = md.ArchiveID - 1)
    ) SELECT [from], [to], ([to]-[from])+1 [total missing]
    From CTERange 
    ORDER BY ([to]-[from])+1 DESC;


from     to     total missing
------- ------- --------------
6        6      1 
8        8      1
11       14     4
吃兔兔 2024-08-02 03:01:39

所有给出的解决方案都太复杂了吗?
这不是更简单吗:

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
        )

Aren't all given solutions way too complex?
wouldn't this be much simpler:

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
        )
小伙你站住 2024-08-02 03:01:39

这是我对此问题的解释,将内容放置在一个表变量中,我可以在脚本的其余部分轻松访问该变量。

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

This is my interpretation of this issue, placing the contents in a Table variable that I can easily access in the remainder of my script.

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
日久见人心 2024-08-02 03:01:39

只是为了好玩,我决定发布我的解决方案。
我的表中有一个身份列,我想找到丢失的发票号码。
我回顾了我能找到的所有示例,但它们不够优雅。

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

Just for fun, I decided to post my solution.
I had an identity column in my table and I wanted to find missing invoice numbers.
I reviewed all the examples I could find but they were not elegant enough.

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
﹉夏雨初晴づ 2024-08-02 03:01:39
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

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

我一直在寻找解决方案并找到了很多答案。 这是我用过的,效果非常好。 我希望这可以帮助任何寻找类似答案的人。

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

I found this answer here:
http://sql-developers.blogspot.com/2012/10/how-to-find-missing-identitysequence.html

I was looking for a solution and found many answers. This is the one I used and it worked very well. I hope this helps anyone looking for a similar answer.

温馨耳语 2024-08-02 03:01:39
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
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
指尖凝香 2024-08-02 03:01:39

创建一个有用的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

Create a useful Tally table:

-- 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

Index it, or make that single column as PK.
Then use EXCEPT to get your missing number.

select Id from Tally where Id <= (select max(Id) from TestTable)
except
select Id from TestTable
微凉 2024-08-02 03:01:39

您还可以使用 CTE 之类的东西来生成完整序列:

create table #tmp(sequence int)

insert into #tmp(sequence) values (1)
insert into #tmp(sequence) values (2)
insert into #tmp(sequence) values (3)
insert into #tmp(sequence) values (5)
insert into #tmp(sequence) values (6)
insert into #tmp(sequence) values (8)
insert into #tmp(sequence) values (10)
insert into #tmp(sequence) values (11)
insert into #tmp(sequence) values (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

嗯 - 由于某种原因,格式在这里不起作用? 任何人都可以看到问题吗?

You could also solve using something like a CTE to generate the full sequence:

create table #tmp(sequence int)

insert into #tmp(sequence) values (1)
insert into #tmp(sequence) values (2)
insert into #tmp(sequence) values (3)
insert into #tmp(sequence) values (5)
insert into #tmp(sequence) values (6)
insert into #tmp(sequence) values (8)
insert into #tmp(sequence) values (10)
insert into #tmp(sequence) values (11)
insert into #tmp(sequence) values (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

Hmmmm - the formatting is not working on here for some reason? Can anyone see the problem?

翻了热茶 2024-08-02 03:01:39

我做了一个过程,这样你就可以发送表名和密钥,结果是给定表中缺失数字的列表

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

create PROCEDURE [dbo].[action_FindMissing_Autoincremnt]
(
@tblname as nvarchar(50),
@tblKey as nvarchar(50)
)
AS
BEGIN
    SET NOCOUNT ON;

declare @qry nvarchar(4000)



set @qry = 'declare @min int ' 
set @qry = @qry + 'declare @max int '

set @qry = @qry +'select @min = min(' + @tblKey + ')'
set @qry = @qry + ', @max = max('+ @tblKey +') '
set @qry = @qry + ' from '+ @tblname 

set @qry = @qry + ' create table #tmp (Field_No int)
while @min <= @max
begin
   if not exists (select * from '+ @tblname +' where '+ @tblKey +' = @min)
      insert into #tmp (Field_No) values (@min)
   set @min = @min + 1
end
select * from #tmp order by Field_No
drop table #tmp '

exec sp_executesql @qry 

END
GO

i had made a proc so you can send the table name and the key and the result is a list of missing numbers from the given table

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

create PROCEDURE [dbo].[action_FindMissing_Autoincremnt]
(
@tblname as nvarchar(50),
@tblKey as nvarchar(50)
)
AS
BEGIN
    SET NOCOUNT ON;

declare @qry nvarchar(4000)



set @qry = 'declare @min int ' 
set @qry = @qry + 'declare @max int '

set @qry = @qry +'select @min = min(' + @tblKey + ')'
set @qry = @qry + ', @max = max('+ @tblKey +') '
set @qry = @qry + ' from '+ @tblname 

set @qry = @qry + ' create table #tmp (Field_No int)
while @min <= @max
begin
   if not exists (select * from '+ @tblname +' where '+ @tblKey +' = @min)
      insert into #tmp (Field_No) values (@min)
   set @min = @min + 1
end
select * from #tmp order by Field_No
drop table #tmp '

exec sp_executesql @qry 

END
GO
此生挚爱伱 2024-08-02 03:01:39

此查询生成一个范围从 1 到 15 的序列。(根据您所需的范围进行更改)

WITH AllNumbers AS (
  SELECT 1 AS number
  UNION ALL
  SELECT number + 1
  FROM dataentry
  WHERE number < 15
)

SELECT number
FROM AllNumbers
WHERE number NOT IN (SELECT number FROM dataentry)

通过选择 cte 表达式中没有的数字,您将获得缺失的数字。

This query generates a sequence that ranges from 1 to 15. (Change according to your desired range)

WITH AllNumbers AS (
  SELECT 1 AS number
  UNION ALL
  SELECT number + 1
  FROM dataentry
  WHERE number < 15
)

SELECT number
FROM AllNumbers
WHERE number NOT IN (SELECT number FROM dataentry)

By selecting the numbers not in the cte expression you would get the missing numbers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文