返回不在SQL列表中的最小整数

时间:2014-07-05 15:16:16

标签: sql sqlite

假设您有一个只允许正整数的表T(A),例如:

1,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18

在上面的示例中,结果为10。我们始终可以使用ORDER BYDISTINCT来排序和删除重复项。但是,为了找到列表中没有的最小整数,我提出了以下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中实现这一目标,还是应该采用完全不同的方向来解决这个问题?

8 个答案:

答案 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)

SQL Fiddle

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

http://sqlfiddle.com/#!7/720cc/3

答案 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.