我正在开发一个必须为元素分配数字代码的应用程序。这个代码不是连续的,我的想法是不要将它们插入到数据库中,直到有相关元素,但我想在sql中找到未分配的代码,我不知道该怎么做。
有什么想法吗? 感谢!!!
修改1
表格可以这么简单:
code | element
-----------------
3 | three
7 | seven
2 | two
我想要这样的东西:1,4,5,6。没有任何其他桌子。
修改2
感谢您的反馈,您的回答非常有用。
答案 0 :(得分:6)
如果未分配代码,则会返回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
答案 1 :(得分:1)
与使用纯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,'九')时,它也生成了8-8的范围。显然,对于'无限'的合适定义,您还有另外两个可能的范围:
-infinity
.. MIN(code)-1
MAX(code)+1
.. +infinity
请注意:
但是,如果你想这样做,这是一种方法。
答案 2 :(得分:0)
这与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
修改强> 当然,这不是理想的解决方案。如果您有很多元素或经常检查不存在的代码,则可能会导致性能问题。