提问人:Pascal 提问时间:9/14/2023 最后编辑:E_net4Pascal 更新时间:9/14/2023 访问量:74
选择 postgres 列中不存在的值(无上限)
Select values that are not present in a postgres column (without upper limit)
问:
给定一个 postgres 表 foo,其中包含一个有一些间隙的列。有没有办法在不循环或使用过大的 to from 或 against 的情况下获取所述列中不存在的值?external_id BIGINT
generate_sequence
exclude
join
n
假设它有带有 external_ids 的行,我希望它返回顺序值,它应该返回 .下一个选择(假设没有更改)应该返回 etc。因此,应该返回间隙和持续上升的顺序 ID。我可以做这样的事情1, 3, 5, 7
5
2, 4, 6, 8, 9
10, 11, 12, 13, 14
WITH
id_series AS (
SELECT
generate_series(1, 10) AS ids
)
SELECT
id_series.ids
FROM
id_series
left join known_ids ki on id_series.ids = kid.id
where
ki.id is null
limit 5;
但是,如果序列不够大,无法找到未使用的 ID,则可能无法返回足够的未使用 ID,只要返回了 5 个 ID,就必须循环。
我的表当前包含介于 50,000 和 1,800,000,000 之间的 ID。有些间隙有几百万个 ID 宽,有些其他范围没有另外几百万个间隙(可能需要多次循环或使用非常大的序列)
有没有聪明有效的方法可以解决这个问题?
这就是我这样做的原因。该表包含来自外部数据源。必须使用单个 ID 查询此数据源。数据源会随时间推移公开其实体。因此,ID 10 亿可能在 ID 5 之前是“公共”的。所以我需要知道我还没有收到响应的外部 ID 并定期查询它们。正如我之前所说,这是我无法更改的,因为我无法控制外部数据源。这是我无法更改的实际业务需求。external_ids
答:
无论如何,您的查询都必须扫描整个表。我不认为使用类似的东西会太低效
SELECT generate_series(
(SELECT MIN(external_id) FROM known),
(SELECT MAX(external_id) FROM known)
)
EXCEPT
SELECT external_id FROM known
当然,这不会返回低于或高于现有 ID 的 id,并且生成的 id 可能少于您需要的值,但您可以在应用程序逻辑中轻松处理它。或使用 .n
generate_series(1, max(external_id)+n)
如果实际上不需要单个 ID,而是需要每个间隙的范围,请查看间隙和孤岛查询,例如在 SQL 中查找序列的间隙,而无需创建其他表。
如果您不需要一次所有间隙,而只需要下一个间隙,并且不超过值,则可以编写迭代算法,使用递归 CTE 找到一个又一个间隙(直到您有足够的值)。n
评论
EXCEPT
对我来说非常慢,但是,在已知表中找不到任何东西的左连接在有限制的情况下非常快(这很好,因为我无论如何都在批量查询并且不需要一次所有 id)。我猜是因为generate_series够懒了。只有当使用偏移量时,它才会变慢,但这可以通过通过generate_series调用的下限进行偏移来解决。IDK 为什么我的印象是这会很慢..感谢您实际给出:)答案
评论
external_id