我正在开发一个必须为元素分配数字代码的应用程序。这些代码不是连续的,我的想法是在有相关元素之前不要将它们插入数据库中,但我想在 sql 问题中找到未分配的代码,我不知道该怎么做。
有任何想法吗?谢谢!!!
编辑 1
该表可以如此简单:
code | element
-----------------
3 | three
7 | seven
2 | two
我想要这样的东西:1、4、5、6。没有任何其他表。
编辑 2
感谢您的反馈,您的回答非常有帮助。
NULL
如果未分配代码,这将返回:
SELECT assigned_codes.code
FROM codes
LEFT JOIN
assigned_codes
ON assigned_codes.code = codes.code
WHERE codes.code = @code
这将返回所有未分配的代码:
SELECT codes.code
FROM codes
LEFT JOIN
assigned_codes
ON assigned_codes.code = codes.code
WHERE assigned_codes.code IS NULL
没有纯粹SQL
的方法可以完全按照您的意愿去做。
在Oracle
中,您可以执行以下操作:
SELECT lvl
FROM (
SELECT level AS lvl
FROM dual
CONNECT BY
level <=
(
SELECT MAX(code)
FROM elements
)
)
LEFT OUTER JOIN
elements
ON code = lvl
WHERE code IS NULL
在PostgreSQL
中,您可以执行以下操作:
SELECT lvl
FROM generate_series(
1,
(
SELECT MAX(code)
FROM elements
)) lvl
LEFT OUTER JOIN
elements
ON code = lvl
WHERE code IS NULL
与使用纯 SQL 无法做到这一点的断言相反,这里有一个反例说明如何做到这一点。(请注意,我并没有说这很容易 - 但是,它是可能的。)假设表的名称value_list
带有列code
并且value
如编辑中所示(为什么每个人都忘记在问题中包含表名?):
SELECT b.bottom, t.top
FROM (SELECT l1.code - 1 AS top
FROM value_list l1
WHERE NOT EXISTS (SELECT * FROM value_list l2
WHERE l2.code = l1.code - 1)) AS t,
(SELECT l1.code + 1 AS bottom
FROM value_list l1
WHERE NOT EXISTS (SELECT * FROM value_list l2
WHERE l2.code = l1.code + 1)) AS b
WHERE b.bottom <= t.top
AND NOT EXISTS (SELECT * FROM value_list l2
WHERE l2.code >= b.bottom AND l2.code <= t.top);
from 子句中的两个并行查询生成的值分别位于表中值范围的间隙的顶部和底部。然后限制这两个列表的叉积,使得底部不大于顶部,并且在底部和顶部之间的原始列表中没有值。
在样本数据上,这会产生范围 4-6。当我添加一个额外的行(9,'9')时,它还生成了 8-8 范围。显然,对于“无穷大”的合适定义,您还有另外两个可能的范围:
-infinity
..MIN(code)-1
MAX(code)+1
..+infinity
注意:
但是,如果您想这样做,这是一种方法。
这与 Quassnoi 发表的想法相同。我只是用 T-SQL 之类的代码将所有想法联系在一起。
DECLARE
series @table(n int)
DECLARE
max_n int,
i int
SET i = 1
-- max value in elements table
SELECT
max_n = (SELECT MAX(code) FROM elements)
-- fill @series table with numbers from 1 to n
WHILE i < max_n BEGIN
INSERT INTO @series (n) VALUES (i)
SET i = i + 1
END
-- unassigned codes -- these without pair in elements table
SELECT
n
FROM
@series AS series
LEFT JOIN
elements
ON
elements.code = series.n
WHERE
elements.code IS NULL
编辑: 当然,这不是理想的解决方案。如果您有很多元素或经常检查不存在的代码,这可能会导致性能问题。