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 3
和 6
。
更新
如果您想要查询 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
我使用以下技术:
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
我想知道是否可以创建一个 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 3
和 6
。
更新
如果您想要查询 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
我使用以下技术:
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