我有一个表具有唯一的自动增量主键.随着时间的推移,可能会从表中删除条目,因此该字段的值中存在"漏洞".例如,表数据可能如下:
ID | Value | More fields...
---------------------------------
2 | Cat | ...
3 | Fish | ...
6 | Dog | ...
7 | Aardvark | ...
9 | Owl | ...
10 | Pig | ...
11 | Badger | ...
15 | Mongoose | ...
19 | Ferret | ...
Run Code Online (Sandbox Code Playgroud)
我对将返回表中缺少ID列表的查询感兴趣.对于上述数据,预期结果如下:
ID
----
1
4
5
8
12
13
14
16
17
18
Run Code Online (Sandbox Code Playgroud)
笔记:
上述要求的缺点是列表不会返回在ID 19之后创建且已删除的ID.我目前正在代码中解决这个问题,因为我持有创建的最大ID.但是,如果查询可以作为参数MaxID,并且还返回当前max和MaxID之间的那些ID,那将是一个很好的"奖励"(但肯定不是必须的).
我目前正在使用MySQL,但考虑转移到SQL Server,所以我希望查询适合两者.此外,如果您使用的是无法在SQLite上运行的任何内容,请提及它,谢谢.
Eri*_*ric 30
这个问题经常出现,遗憾的是,最常见(也是最便携)的答案是创建一个临时表来保存应该存在的ID ,并进行左连接.MySQL和SQL Server之间的语法非常相似.唯一真正的区别是临时表语法.
在MySQL中:
declare @id int
declare @maxid int
set @id = 1
select @maxid = max(id) from tbl
create temporary table IDSeq
(
id int
)
while @id < @maxid
begin
insert into IDSeq values(@id)
set @id = @id + 1
end
select
s.id
from
idseq s
left join tbl t on
s.id = t.id
where t.id is null
drop table IDSeq
Run Code Online (Sandbox Code Playgroud)
在SQL Server中:
declare @id int
declare @maxid int
set @id = 1
select @maxid = max(id) from tbl
create table #IDSeq
(
id int
)
while @id < @maxid --whatever you max is
begin
insert into #IDSeq values(@id)
set @id = @id + 1
end
select
s.id
from
#idseq s
left join tbl t on
s.id = t.id
where t.id is null
drop table #IDSeq
Run Code Online (Sandbox Code Playgroud)
小智 21
这是SQL Server的查询:
;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);
Run Code Online (Sandbox Code Playgroud)
希望这是有帮助的.
Nik*_*rns 21
我登陆这个页面希望找到SQLITE的解决方案,因为这是我在为SQLITE搜索同样的问题时找到的唯一答案.
我找到的最终解决方案是从这篇文章 Float Middle Blog - SQLITE回答
希望它可以帮助别人:-)
简单的解决方案是:
SELECT DISTINCT id +1
FROM mytable
WHERE id + 1 NOT IN (SELECT DISTINCT id FROM mytable);
Run Code Online (Sandbox Code Playgroud)
天才.
Per*_*ren 10
我知道这是一个古老的问题并且已经有了一个可接受的答案,但使用临时表并不是必需的.固定格式(抱歉双帖).
DECLARE @TEST_ID integer, @LAST_ID integer, @ID integer
SET @TEST_ID = 1 -- start compare with this ID
SET @LAST_ID = 100 -- end compare with this ID
WHILE @TEST_ID <= @LAST_ID
BEGIN
SELECT @ID = (SELECT <column> FROM <table> WHERE <column> = @TEST_ID)
IF @ID IS NULL
BEGIN
PRINT 'Missing ID: ' + CAST(@TEST_ID AS VARCHAR(10))
END
SET @TEST_ID = @TEST_ID + 1
END
Run Code Online (Sandbox Code Playgroud)
这是仅限 Oracle 的解决方案。它没有解决完整的问题,但留在这里供其他可能使用 Oracle 的人使用。
select level id -- generate 1 .. 19
from dual
connect by level <= 19
minus -- remove from that set
select id -- everything that is currently in the
from table -- actual table
Run Code Online (Sandbox Code Playgroud)
仅限PostgreSQL,受此处其他答案的启发。
SELECT all_ids AS missing_ids
FROM generate_series((SELECT MIN(id) FROM your_table), (SELECT MAX(id) FROM your_table)) all_ids
EXCEPT
SELECT id FROM your_table
Run Code Online (Sandbox Code Playgroud)