Man*_*eta 5 postgresql postgresql-8.4 generate-series
SELECT commandid
FROM results
WHERE NOT EXISTS (
SELECT *
FROM generate_series(0,119999)
WHERE generate_series = results.commandid
);
Run Code Online (Sandbox Code Playgroud)
我有一个results类型的列,int但各种测试失败,并没有添加到表中.我想创建一个返回commandid未找到的列表的查询results.我认为上面的查询会做我想要的.但是,如果我使用超出预期可能范围的范围commandid(如负数),它甚至不起作用.
Cra*_*ger 14
给出样本数据:
create table results ( commandid integer primary key);
insert into results (commandid) select * from generate_series(1,1000);
delete from results where random() < 0.20;
Run Code Online (Sandbox Code Playgroud)
这有效:
SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
WHERE NOT EXISTS (SELECT 1 FROM results WHERE commandid = s.i);
Run Code Online (Sandbox Code Playgroud)
这个替代配方也是如此:
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;
Run Code Online (Sandbox Code Playgroud)
以上两种情况似乎都会在我的测试中产生相同的查询计划,但您应该与数据库中的数据进行比较,EXPLAIN ANALYZE以查看哪种方法最佳.
请注意,NOT IN我没有NOT EXISTS在一个公式中使用子查询,而在另一个公式中使用普通子查询OUTER JOIN.这对DB服务器更容易优化这些,它避免了能与出现的混乱问题,NULL以s NOT IN.
我最初赞成这个OUTER JOIN表述,但至少在9.1中我的测试数据NOT EXISTS表格优化到同一个计划.
NOT IN当系列很大时,两者都会比下面的配方表现更好,就像你的情况一样.NOT IN曾经要求Pg IN对每个被测试的元组进行线性搜索,但是对查询计划的检查表明Pg可能足够聪明,现在可以对其进行散列.该NOT EXISTS(转化为JOIN被查询规划)和JOIN更好地工作.
NOT IN在存在NULL commandid的情况下,该公式既令人困惑又效率低下:
SELECT s.i AS missing_cmd
FROM generate_series(0,1000) s(i)
WHERE s.i NOT IN (SELECT commandid FROM results);
Run Code Online (Sandbox Code Playgroud)
所以我会避免它.有1,000,000行,另外两行在1.2秒内完成,NOT IN配方运行CPU限制,直到我感到无聊并取消它.
正如我在评论中提到的,您需要执行与上述查询相反的操作.
SELECT
generate_series
FROM
generate_series(0, 119999)
WHERE
NOT generate_series IN (SELECT commandid FROM results);
Run Code Online (Sandbox Code Playgroud)
此时,您应该找到commandid所选范围内的列中不存在的值.
| 归档时间: |
|
| 查看次数: |
4278 次 |
| 最近记录: |