0

为什么下一个 Fiddle 不给我 102 ?我正在寻找两列中都不存在的最小数字。

注意:一列是数字,另一列是 varchar。

SELECT NVL(MIN(a1.id_int)+1, 111)
  FROM bPEOPLE a1
 WHERE NOT EXISTS (SELECT 1
                     FROM PEOPLE a2
                    WHERE a2.id_int=a1.id_int+1
                   )
   AND NOT EXISTS ( SELECT 1
                      FROM PEOPLE a3
                     WHERE TO_NUMBER(a3.id_str)=a1.id_int+1
                   )
   AND a1.id_int + 1 > 100
   AND a1.id_int + 1 < 110;

Sql 小提琴

4

4 回答 4

2

因为你的表达:

NVL(MIN(a1.id_int)+1, 111)

仅引用 int 列,其中下一个值为 108。

您需要将两列合并为一列,然后得到 MIN:

SELECT  NVL(MIN(a.id_int)+1, 111) as next_id
FROM    (   SELECT id_int
            FROM PEOPLE
            UNION ALL
            SELECT TO_NUMBER(id_str) AS id_int
            FROM PEOPLE
        ) a
WHERE   NOT EXISTS
        (   SELECT  1
            FROM    PEOPLE b
            WHERE   a.id_int + 1 IN (b.id_int, TO_NUMBER(b.id_str))
        );

SQL Fiddle 示例

于 2013-08-22T12:18:11.763 回答
1

您没有得到 102,因为您从id_int列开始,然后添加1. 您必须在id_int列中有 101 才能有机会获得 102。

换句话说,您的错误是,您从 开始MIN(a1.id_int)并忽略MIN(TO_NUMBER(a3.id_str))

这可能是你想要的

SELECT NVL(MIN(n)+1, 111) FROM
(
  SELECT id_int as n FROM PEOPLE
  UNION
  SELECT TO_NUMBER(id_str) as n FROM PEOPLE
) p
WHERE
  NOT EXISTS
  (
    SELECT
      1
    FROM
      PEOPLE a2
    WHERE
      a2.id_int=n+1
  )
  AND
  NOT EXISTS
    (
      SELECT
        1
      FROM
        PEOPLE a3
      WHERE
        TO_NUMBER(a3.id_str)=n+1
    )
AND n + 1 > 100
AND n + 1 < 110;
于 2013-08-22T12:15:34.377 回答
0

您的not exists子句说“排除另一行的值比当前行大一的行”。唯一适用的行是最后一行,而您的问题暗示您想要第一行。

要解决此问题,您只需将子句中的 移动+1not exists谓词中的其他列。

此外,在小提琴中,您正在递增包含 105 的整数值。如果要递增 101,则需要id_str在函数中选择列。

SELECT
  NVL(MIN(a1.id_str)+1, 111)
FROM
  PEOPLE a1
WHERE
  NOT EXISTS
  (
    SELECT
      1
    FROM
      PEOPLE a2
    WHERE
      a2.id_int+1=a1.id_int
  )
  AND
  NOT EXISTS
    (
      SELECT
        1
      FROM
        PEOPLE a3
      WHERE
        TO_NUMBER(a3.id_str)+1=a1.id_int
    )
AND a1.id_int + 1 > 100
AND a1.id_int + 1 < 110;

最后,在提供的数据集中,您实际上不需要应用该min函数, (101, 105) 行是唯一选择的行。但是,您可能仍需要对真实数据集取最小值。

于 2013-08-25T20:13:32.813 回答
0

我不确定为什么它会给你错误的结果,但我认为你可以创建两列的并集并找到没有下一个的 min 并添加一个

尝试

SELECT MIN(t1.id)+1
FROM (
    SELECT CAST(id_str AS INT) id
    FROM people
    UNION
    SELECT id_int
    FROM people
) t1
LEFT JOIN (
    SELECT CAST(id_str AS INT) id
    FROM people
    UNION
    SELECT id_int
    FROM people
) t2 ON t2.id = t1.id+1
WHERE t2.id IS NULL

演示

于 2013-08-22T12:17:10.547 回答