我有一个具有用户ID列的表,用户可以选择要在表中添加的用户ID。我想知道是否有一个sql代码可以指向未使用的用户ID列表,甚至只是最小的未使用ID?
例如,我有以下ID
USER_ID 1 2 3 五 6 7 8 10
我想知道是否有办法选择4甚至选择4和9?
答案 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存在较大差距,则不应该成为问题。 (事实上,有些人会说,为了避免用户篡改信息以找到安全漏洞,甚至可以更好