如何find与SQL运行计数器“差距”?
我想find一个SQL表中的第一个“差距”在柜台列。 例如,如果有值1,2,4和5我想找出3。
我当然可以按顺序获取值并手动执行,但是我想知道是否有办法在SQL中执行此操作。
另外,它应该是相当标准的SQL,与不同的DBMS一起工作。
 在MySQL和PostgreSQL : 
 SELECT id + 1 FROM mytable mo WHERE NOT EXISTS ( SELECT NULL FROM mytable mi WHERE mi.id = mo.id + 1 ) ORDER BY id LIMIT 1 
 在SQL Server : 
 SELECT TOP 1 id + 1 FROM mytable mo WHERE NOT EXISTS ( SELECT NULL FROM mytable mi WHERE mi.id = mo.id + 1 ) ORDER BY id 
 在Oracle : 
 SELECT * FROM ( SELECT id + 1 AS gap FROM mytable mo WHERE NOT EXISTS ( SELECT NULL FROM mytable mi WHERE mi.id = mo.id + 1 ) ORDER BY id ) WHERE rownum = 1 
  ANSI (无处不在,效率最低): 
 SELECT MIN(id) + 1 FROM mytable mo WHERE NOT EXISTS ( SELECT NULL FROM mytable mi WHERE mi.id = mo.id + 1 ) 
支持滑动窗口function的系统:
 SELECT -- TOP 1 -- Uncomment above for SQL Server 2012+ previd FROM ( SELECT id, LAG(id) OVER (ORDER BY id) previd FROM mytable ) q WHERE previd <> id - 1 ORDER BY id -- LIMIT 1 -- Uncomment above for PostgreSQL 
你的答案一切工作正常,如果你有第一个值id = 1,否则这个差距将不会被检测到。 例如,如果您的表ID值是3,4,5,您的查询将返回6。
我做了这样的事情
 SELECT MIN(ID+1) FROM ( SELECT 0 AS ID UNION ALL SELECT MIN(ID + 1) FROM TableX) AS T1 WHERE ID+1 NOT IN (SELECT ID FROM TableX) 
 第一件事进入我的脑海。 不知道这样做是否是一个好主意,但应该工作。 假设表是t ,列是c : 
SELECT t1.c+1 AS gap FROM t as t1 LEFT OUTER JOIN t as t2 ON (t1.c+1=t2.c) WHERE t2.c IS NULL ORDER BY gap ASC LIMIT 1
编辑:这可能是一个更快的(和更短!):
SELECT min(t1.c)+1 AS gap FROM t as t1 LEFT OUTER JOIN t as t2 ON (t1.c+1=t2.c) WHERE t2.c IS NULL
这在SQL Server中工作 – 不能在其他系统中testing,但它似乎标准…
 SELECT MIN(t1.ID)+1 FROM mytable t1 WHERE NOT EXISTS (SELECT ID FROM mytable WHERE ID = (t1.ID + 1)) 
你也可以添加一个起点到where子句…
 SELECT MIN(t1.ID)+1 FROM mytable t1 WHERE NOT EXISTS (SELECT ID FROM mytable WHERE ID = (t1.ID + 1)) AND ID > 2000 
所以,如果你有2000年,2001年,2002年和2005年,2003年和2004年不存在,它将返回到2003年。
有没有一个非常标准的SQL方法来做到这一点,但有一些forms的限制条款,你可以做
 SELECT `table`.`num` + 1 FROM `table` LEFT JOIN `table` AS `alt` ON `alt`.`num` = `table`.`num` + 1 WHERE `alt`.`num` IS NULL LIMIT 1 
(MySQL,PostgreSQL)
要么
 SELECT TOP 1 `num` + 1 FROM `table` LEFT JOIN `table` AS `alt` ON `alt`.`num` = `table`.`num` + 1 WHERE `alt`.`num` IS NULL 
(SQL Server)
要么
 SELECT `num` + 1 FROM `table` LEFT JOIN `table` AS `alt` ON `alt`.`num` = `table`.`num` + 1 WHERE `alt`.`num` IS NULL AND ROWNUM = 1 
(Oracle)的
内部连接到具有所有可能值的视图或序列。
没有桌子? 制作一张桌子。 为了这个,我总是保留一张虚拟桌子。
 create table artificial_range( id int not null primary key auto_increment, name varchar( 20 ) null ) ; -- or whatever your database requires for an auto increment column insert into artificial_range( name ) values ( null ) -- create one row. insert into artificial_range( name ) select name from artificial_range; -- you now have two rows insert into artificial_range( name ) select name from artificial_range; -- you now have four rows insert into artificial_range( name ) select name from artificial_range; -- you now have eight rows --etc. insert into artificial_range( name ) select name from artificial_range; -- you now have 1024 rows, with ids 1-1024 
然后,
  select a.id from artificial_range a where not exists ( select * from your_table b where b.counter = a.id) ; 
我猜:
 SELECT MIN(p1.field) + 1 as gap FROM table1 AS p1 INNER JOIN table1 as p3 ON (p1.field = p3.field + 2) LEFT OUTER JOIN table1 AS p2 ON (p1.field = p2.field + 1) WHERE p2.field is null; 
 对于PostgreSQL 
一个使用recursion查询的例子。
这可能是有用的,如果你想find一个特定的范围内的差距(它将工作,即使表是空的,而其他的例子不会)
 WITH RECURSIVE a(id) AS (VALUES (1) UNION ALL SELECT id + 1 FROM a WHERE id < 100), -- range 1..100 b AS (SELECT id FROM my_table) -- your table ID list SELECT a.id -- find numbers from the range that do not exist in main table FROM a LEFT JOIN b ON b.id = a.id WHERE b.id IS NULL -- LIMIT 1 -- uncomment if only the first value is needed 
这个是迄今为止提到的一切。 它包含0作为起始点,如果不存在任何值,则默认为0。 我还为多值键的其他部分添加了适当的位置。 这只在SQL Server上进行过testing。
 select MIN(ID) from ( select 0 ID union all select [YourIdColumn]+1 from [YourTable] where --Filter the rest of your key-- ) foo left join [YourTable] on [YourIdColumn]=ID and --Filter the rest of your key-- where [YourIdColumn] is null 
 select min([ColumnName]) from [TableName] where [ColumnName]-1 not in (select [ColumnName] from [TableName]) and [ColumnName] <> (select min([ColumnName]) from [TableName]) 
这里是标准的SQL解决scheme,可以在所有的数据库服
 select min(counter + 1) FIRST_GAP from my_table a where not exists (select 'x' from my_table b where b.counter = a.counter + 1) and a.counter <> (select max(c.counter) from my_table c); 
参见行动
- PL / SQL通过Oracle的livesql ,
- MySQL通过sqlfiddle ,
- PostgreSQL通过sqlfiddle
- MS Sql通过sqlfiddle
它适用于空表或负值。 刚刚在SQL Server 2012中testing过
  select min(n) from ( select case when lead(i,1,0) over(order by i)>i+1 then i+1 else null end n from MyTable) w 
如果你使用火鸟3,这是最优雅和简单的:
 select RowID from ( select `ID_Column`, Row_Number() over(order by `ID_Column`) as RowID from `Your_Table` order by `ID_Column`) where `ID_Column` <> RowID rows 1