如何在列中查找未使用的ID?

时间:2009-08-24 04:11:43

标签: sql

  

可能重复:
  SQL query to find Missing sequence numbers

我有一个具有用户ID列的表,用户可以选择要在表中添加的用户ID。我想知道是否有一个sql代码可以指向未使用的用户ID列表,甚至只是最小的未使用ID?

例如,我有以下ID

USER_ID 1 2 3 五 6 7 8 10

我想知道是否有办法选择4甚至选择4和9?

5 个答案:

答案 0 :(得分:6)

您可以尝试使用“NOT IN”子句:

select
    user_id
from table
where
    user_id not in (select user_id from another_table)

像这样:

select
    u1.user_id + 1 as start
from users as u1
  left outer join users as u2 on u1.user_id + 1 = u2.id
where
    u2.id is null

来自here

答案 1 :(得分:2)

这取决于您使用的数据库。如果您使用的是Oracle,那么这样的东西会起作用: 第1步:找出表中userid的最大值:

    select max(userid) from tbl_userid 

    let this number be m

步骤2:找出foll查询中rownum的最大值

    select rownum from all_objects

步骤3:如果最大值大于m,则可以使用foll查询列出未使用的用户ID

    select user_id 
    from tbl_userid
    where user_id NOT IN (select rownum from all_objects)

如果第2步返回的最大值小于m,则可以将查询调整为以下

    select user_id 
    from tbl_userid
    where user_id NOT IN 
                  (select rownum 
                   from (select * 
                         from all_objects 
                         UNION ALL 
                         select * from all_objects)
                  )

重复UNION ALL,直到达到max(rownum)> = m

如果您使用的是SQL Server,请告诉我。在sql server中没有直接等效的ROWNUM伪列,但有使用RANK()函数的变通方法。

答案 2 :(得分:1)

鉴于SQL通常是一种基于集合的语言,我认为这样做的唯一方法就是创建完整的ID集合,并将外部联接到没有ID匹配的表格。问题是,如果您的表具有大量记录,则必须生成包含从1到MAX(USER_ID)的每个ID的临时表。如果有一张包含数万或数亿条记录的表,那可能会非常慢。

出于好奇,为什么你需要知道ID漏洞?是否有某些特定原因,或者您只是想“不浪费”身份证?鉴于寻找漏洞的处理工作,我认为让它们变得更有效率。

答案 3 :(得分:1)

以下是使用SQL Server 2005或更高版本执行此操作的一种方法。它可能会或可能不会对您有效:

insert into T values
  (1),(2),(3),(5),(6),(9),(11);

with Trk as (
  select userid,
    row_number() over (
      order by userid
    ) as rk
  from T
), Truns(start,finish,gp) as (
     select -1+min(userid), 1+max(userid),
     userid-rk
     from Trk
     group by userid-rk
), Tregroup as (
  select start, finish,
    row_number() over (
      order by gp 
    ) as rk
  from Truns
), Tpre as (
  select a.finish, b.start
  from Tregroup as a full outer join Tregroup as b
  on a.rk + 1 = b.rk
) 
  select
    rtrim(finish) + case when start = finish then '' else + '-' + rtrim(start) end as gap
  from Tpre
  where finish+start is not null
drop table T;

答案 4 :(得分:0)

没有循环遍历所有id(可能使用二叉搜索树逻辑?)我没有给你一个好的答案。

我会问你想要的是什么?就其性质而言,ID本质上毫无意义 - 他们所做的只是识别某些数据,而不是描述它,因此如果您的用户ID存在较大差距,则不应该成为问题。 (事实上​​,有些人会说,为了避免用户篡改信息以找到安全漏洞,甚至可以更好