加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

PostgreSQL:如何使用generate_series()找出列中缺少的数字?

发布时间:2020-12-13 18:09:41 所属栏目:百科 来源:网络整理
导读:SELECT commandid FROM results WHERE NOT EXISTS ( SELECT * FROM generate_series(0,119999) WHERE generate_series = results.commandid ); 我在类型为int的结果中有一列,但各种测试失败并且没有添加到表中.我想创建一个查询,返回在结果中找不到的command
SELECT commandid 
FROM results 
WHERE NOT EXISTS (
    SELECT * 
    FROM generate_series(0,119999) 
    WHERE generate_series = results.commandid 
    );

我在类型为int的结果中有一列,但各种测试失败并且没有添加到表中.我想创建一个查询,返回在结果中找不到的commandid列表.我认为上面的查询会做我想要的.但是,如果我使用超出预期可能的commandid范围的范围(如负数),它甚至不起作用.

给出样本数据:
create table results ( commandid integer primary key);
insert into results (commandid) select * from generate_series(1,1000);
delete from results where random() < 0.20;

这有效:

SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
WHERE NOT EXISTS (SELECT 1 FROM results WHERE commandid = s.i);

这个替代配方也是如此:

SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
LEFT OUTER JOIN results ON (results.commandid = s.i) 
WHERE results.commandid IS NULL;

以上两种情况似乎都会在我的测试中产生相同的查询计划,但是您应该使用EXPLAIN ANALYZE与数据库中的数据进行比较,以确定哪种方法最佳.

说明

请注意,而不是NOT IN我在一个公式中使用了带有子查询的NOT EXISTS,而在另一个公式中使用了普通的OUTER JOIN. DB服务器更容易优化这些,并避免了NOT IN中出现NULL的混乱问题.

我最初偏爱OUTER JOIN公式,但至少在9.1中我的测试数据NOT EXISTS表格优化到同一计划.

当系列很大时,两者都会比下面的NOT IN配方表现更好,就像你的情况一样. NOT IN曾经要求Pg对正在测试的每个元组进行IN列表的线性搜索,但是对查询计划的检查表明Pg可能足够聪明,现在可以对其进行哈希处理. NOT EXISTS(由查询计划器转换为JOIN)和JOIN工作得更好.

在存在NULL命令的情况下,NOT IN公式既令人困惑又可能效率低下:

SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
WHERE s.i NOT IN (SELECT commandid FROM results);

所以我会避免它.拥有1,000,000行,另外两行在1.2秒内完成,NOT IN配方运行CPU限制,直到我感到无聊并取消它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读