Mysql 检查整数可用性

Mysql Check integer availability

我想知道是否可以创建一个 return 可用的最小整数的查询。解释起来有点复杂,但是举个例子很方便:

代码:1 2 4 5 6

在这种情况下,我想查询 return 数字 3,因为它是仍然可用的最小整数。

提前致谢。

更新

我有以下表格:

Itens
+----+-----------+------+
| id | name      | code |
+----+-----------+------+
| 1  | produto 1 | 1    |
+----+-----------+------+
| 2  | produto 2 | 2    |
+----+-----------+------+
| 3  | produto 3 | 4    |
+----+-----------+------+
| 4  | produto 4 | 6    |
+----+-----------+------+

Categories
+----+------------+------------+
| id | name       | company_id |
+----+------------+------------+
| 1  | Category 1 |     1      |
+----+------------+------------+
| 2  | Category 2 |     2      |
+----+------------+------------+

Companies
+----+-----------+
| id | name      |
+----+-----------+
| 1  | Company 1 |
+----+-----------+
| 2  | Company 2 |
+----+-----------+

我需要在触发器中为每个公司执行此操作。我尝试了下面的代码,但不起作用。

CREATE TRIGGER `updateCodigoNull`
BEFORE INSERT ON `itens`
FOR EACH ROW
  BEGIN
    IF (NEW.codigo IS NULL)
    THEN
      SET NEW.codigo = (SELECT b.codigo - 1
                        FROM (
                               (SELECT
                                  2 AS 'codigo',
                                  1 AS 'missing',
                                  1 AS 'previous'
                                FROM itens
                                  INNER JOIN item_categories ON itens.category_id = item_categories.id
                                WHERE NOT EXISTS(SELECT 1
                                                 FROM itens
                                                 WHERE codigo = 1) AND item_categories.company_id = 2
                                LIMIT 1)
                               UNION
                               (SELECT
                                  codigo,
                                  IF(@previous != 0 AND @previous < codigo - 1, 1, 0) AS missing,
                                  @previous := codigo
                                FROM itens
                                  INNER JOIN item_categories
                                    ON itens.category_id = item_categories.id
                                  , (SELECT @previous := 0) a
                                WHERE item_categories.company_id = 2
                               )) b
                        WHERE b.missing = 1
                        ORDER BY b.codigo
                        LIMIT 1);
    END IF;
  END

如果这些数字是行 ID,那么您可以使用查询变量来跟踪先前的 ID 和 return 当差异大于 1 时的第一个 ID,例如:

创建并插入脚本:

create table test(id int);
insert into test values(1);
insert into test values(2);
insert into test values(4);
insert into test values(5);
insert into test values(7);

查询:

SELECT b.id - 1
FROM (
    SELECT id, IF(@previous != 0 AND @previous < id - 1, 1, 0) as missing, @previous:= id 
    FROM test , (SELECT @previous := 0) a
    ORDER BY id
    ) b
WHERE b.missing = 1
LIMIT 1;

这将 return 3。如果您想要前 2 个丢失的 ID,那么您可以将 LIMIT 更改为 2,它将 return 36

更新

如果您想要查询 return 值,例如 1 如果它们不存在,那么您可以添加另一个查询和 UNION 结果,例如:

SELECT b.id - 1
FROM (
  SELECT 2 AS 'id', 1 AS 'missing', 1 AS 'previous' FROM test WHERE NOT EXISTS (SELECT 1 FROM test WHERE id = 1) LIMIT 1
  UNION 
  SELECT id, IF(@previous != 0 AND @previous < id - 1, 1, 0) as missing, @previous:= id 
  FROM test , (SELECT @previous := 0) a
  ) b
WHERE b.missing = 1
ORDER BY b.id
LIMIT 1;

上面会return1,下面是SQL Fiddle.

此查询将连接到您的 table 并得到最小缺失是,子查询生成 1000 个整数,它可以轻松扩展为更多。

select MIN(a.numbs) 
from (
    select 1000 -  (a.a + (10 * b.a) + (100 * c.a))  as numbs
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a LEFT JOIN t
ON a.numbs =t.id
WHERE t.id IS NULL

See it working

我使用以下技术:

SELECT i1.codigo + 1 AS unused_codigo
FROM itens AS i1
LEFT OUTER JOIN itens AS i2
  ON i1.codigo + 1 = i2.codigo
WHERE i2.codigo IS NULL

这是有效的,因为外部连接将 return NULL 没有匹配的地方,即没有 i1.codigo + 1 的代码时。这适用于任何间隙,也适用于最后一个table.

中的值

有点复杂。我们还想查找代码 1 是否丢失,因此我们需要使 i1 table 与字面值 0 合并。

您似乎还要求将搜索限制在与公司 2 关联的类别中(虽然这在您的描述中不清楚,但在您的示例查询中)。

SELECT i1.codigo + 1 AS unused_codigo
FROM (
  SELECT 0 AS codigo
  UNION ALL 
  SELECT i.codigo 
  FROM itens AS i 
  JOIN item_categories AS c1 
    ON i.category_id = c1.id AND c1.company_id = 2
) AS i1
LEFT OUTER JOIN (
  itens AS i2 
  JOIN item_categories AS c2 
    ON i2.category_id = c2.id AND c2.company_id = 2
) ON i1.codigo + 1 = i2.codigo
WHERE i2.codigo IS NULL
ORDER BY unused_codigo
LIMIT 1