假设您有一个只允许正整数的表T(A)
,例如:
1,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18
在上面的示例中,结果为10
。我们始终可以使用ORDER BY
和DISTINCT
来排序和删除重复项。但是,为了找到列表中没有的最小整数,我提出了以下SQL
查询:
select list.x + 1
from (select x from (select distinct a as x from T order by a)) as list, T
where list.x + 1 not in T limit 1;
我的想法是开始counter
和1,检查该计数器是否在list
中:如果是,则返回,否则递增并再次查看。但是,我必须将该计数器作为1启动,然后递增。该查询适用于大多数情况,因为在1
中存在一些极端情况。我怎样才能在SQL
中实现这一目标,还是应该采用完全不同的方向来解决这个问题?
答案 0 :(得分:7)
因为SQL适用于集合,所以中间SELECT DISTINCT a AS x FROM t ORDER BY a
是多余的。
在整数列中查找间隙的基本技术是查找当前条目加1不存在的位置。这需要某种自联接。
您的查询并不遥远,但我认为可以简化为:
SELECT MIN(a) + 1
FROM t
WHERE a + 1 NOT IN (SELECT a FROM t)
NOT IN充当一种自我加入。这不会从空桌上产生任何东西,但是否则应该没问题。
答案 1 :(得分:4)
select min(y.a) as a
from
t x
right join
(
select a + 1 as a from t
union
select 1
) y on y.a = x.a
where x.a is null
它甚至可以在空表中使用
答案 2 :(得分:2)
您可以执行以下操作,但您可能还需要定义范围 - 在这种情况下,您可能需要一些UNION
SELECT x.id+1
FROM my_table x
LEFT
JOIN my_table y
ON x.id+1 = y.id
WHERE y.id IS NULL
ORDER
BY x.id LIMIT 1;
答案 3 :(得分:2)
您始终可以创建一个包含从1到X的所有数字的表,然后将该表与您要比较的表连接起来。然后只需在SELECT语句中找到您正在比较的表中不存在的TOP值
SELECT TOP 1 table_with_all_numbers.number, table_with_missing_numbers.number
FROM table_with_all_numbers
LEFT JOIN table_with_missing_numbers
ON table_with_missing_numbers.number = table_with_all_numbers.number
WHERE table_with_missing_numbers.number IS NULL
ORDER BY table_with_all_numbers.number ASC;
答案 4 :(得分:2)
此查询按升序排列(从排名1开始)每个不同的数字,并选择小于其数字的最低排名。如果没有等级低于其数量(即表中没有间隙),则查询返回最大数字+ 1.
select coalesce(min(number),1) from (
select min(cnt) number
from (
select
number,
(select count(*) from (select distinct number from numbers) b where b.number <= a.number) as cnt
from (select distinct number from numbers) a
) t1 where number > cnt
union
select max(number) + 1 number from numbers
) t1
答案 5 :(得分:2)
在SQLite 3.8.3或更高版本中,您可以使用递归common table expression来创建计数器。 在这里,当我们找到不在表中的值时,我们停止计数:
WITH RECURSIVE counter(c) AS (
SELECT 1
UNION ALL
SELECT c + 1 FROM counter WHERE c IN t)
SELECT max(c) FROM counter;
(这适用于空表或缺少1
。)
答案 6 :(得分:2)
另一种方法,这次使用EXCEPT:
SELECT a + 1 AS missing FROM T
EXCEPT
SELECT a FROM T
ORDER BY missing
LIMIT 1;
答案 7 :(得分:1)
SELECT min(t.a) - 1
FROM t
LEFT JOIN t t1 ON t1.a = t.a - 1
WHERE t1.a IS NULL
AND t.a > 1; -- exclude 0
这会找到大于1的最小数字,其中 next-smaller 数字不在同一个表中。丢失了该号码。
这甚至可以用于丢失1.在相反方向检查有多个答案。所有这些都会因失踪而失败。
<强> SQL Fiddle. 强>