Postgresql 数据在一张表中存在,另一张表不满足完整性的查找

有两张表T1,T2,表结构和数据如下:

create table t1 (
  id int
);

create table t2 (
  id int,
  finished int
);

insert into t1 values (1);
insert into t1 values (2);
insert into t1 values (3);
insert into t1 values (4);
insert into t1 values (5);
insert into t1 values (6);

insert into t2 values (1,1);
insert into t2 values (2,0);
insert into t2 values (3,1);
insert into t2 values (4,0);

SQL Fiddle 可以测试SQL语句的执行。

想要实现T1中存在前提下,T2中不存在或者finished=0,也就是查询结果是:2, 4, 5, 6.

一、性能测试:

1. not in:

explain (analyze,verbose,costs,buffers) select ID from T1 where ID not in (select ID from T2 where finished=1);

Total runtime: 0.128 ms

2. not exists:

explain (analyze,verbose,costs,buffers) select ID from T1 where not exists (select 1 from T2 where T1.ID=T2.ID and T2.finished=1);

Total runtime: 0.105 ms

3. left join:

explain (analyze,verbose,costs,buffers) select T1.ID from T1 left join T2 on T1.ID=T2.ID and T2.finished=1 where T2.ID is null;

Total runtime: 0.096 ms

4. 网上还看到一种更快方法,但测试下来此方法不对,所以不讨论:

select ID from T2 where (select count(1) from T1 where T1.ID=T2.ID) = 0; 这条语句查询结果为空

因此在postgresql 9.3 上语句执行速度 left join > not exists > not in

当T1和T2表中ID出现null时,not in 语句会有不同的表现,所以推荐总是用not exists 代替 not in.

二、大数据量性能测试:

在大量数据的时候,not in有严重性能下降的问题,下面是我在i5 2.4GHz MAC pro 13吋上的测试。

department(T1) 为59280条数据,数据长度29字符;dept(T2) 为23633条数据,数据长度29字符。

1. explain analyze select department.id from department where department.id not in (select id from dept where finished=true);

Total runtime: 447073.065 ms

2. explain analyze select department.id from department where not exists (select 1 from dept where department.id=dept.id and finished=true);

Total runtime: 325.732 ms

3. explain analyze select department.id from department left join dept on department.id=dept.id and dept.finished=true where dept.id is null;

Total runtime: 319.869 ms

三、总结:

在Postgresql 9.3上:

not in 不仅性能差,而且逻辑可能有问题。

not exists 性能不错,思考起来比较容易。

left join 性能最好,但总体跟not exists 比也快不了多少,思考稍微有点绕。

下面是一张网上的left join 的图,但找不到出处,有助于理解 left join 的过程:

时间: 2024-08-30 12:00:23

Postgresql 数据在一张表中存在,另一张表不满足完整性的查找的相关文章

Sql从一张表中更改另一张表数据

语法: update table1 set table1.列=table2.列 from table2 where table2.列=table1.列update NFYSP.dbo.PATIENT     setPATIENT_ADDUSERID=OLD.PATIENT_ADDUSERID,PATIENT_UPDATEUSERID=OLD.PATIENT_UPDATEUSERID,PATIENT_UPDATEUSERNAME=OLD.PATIENT_UPDATEUSERNAME,PATIENT

django中数据查找条件是表中的外键对应表的列该如何查找?

1 平常查找表中数据的条件是python中已有的数据类型,通过点运算符可以直接查找.如果条件是表中外键列所对应表的某一列,该如何查询数据?比如 class News(models.Model): title = models.CharField(max_length=50); summary = models.TextField(); url = models.CharField(max_length=150); favorCount = models.IntegerField(default=

mssql字符串分割后的值,把表中不存在的插入表中

字符串分割后的值,把表中不存在的插入表中 --供大家参考 使用场景,自行思考…… --创建表tb1 Create table tb1 ( cola int, colb varchar(50) ) --插入数据 insert into tb1(cola,colb) select 1, 'A' union all select 2, 'B' union all select 3, 'C'; --存储过程 Create proc sp_tbTest @sid int,--ID @str varchar

【猜牌问题】甲乙都知道桌子的抽屉里有16张扑克牌: 红桃A、Q、4 黑桃J、8、4、2、7、3 草色K、Q、5、4、6 方块A、5 教授从这16张牌中挑出一张牌来,并把这张牌的点数告诉甲,把这张牌的花色告诉乙。教授问:你们能推理出是什么牌吗? 甲:我不知道这张牌。 乙:我知道你不知道这张牌。 甲:现在我知道这张牌了。 乙:我也知道了。 请问:这张牌是什么牌?

甲乙都知道桌子的抽屉里有16张扑克牌: 红桃A.Q.4 黑桃J.8.4.2.7.3 草色K.Q.5.4.6 方块A.5 教授从这16张牌中挑出一张牌来,并把这张牌的点数告诉甲,把这张牌的花色告诉乙.教授问:你们能推理出是什么牌吗? 甲:我不知道这张牌.乙:我知道你不知道这张牌.甲:现在我知道这张牌了.乙:我也知道了. 请问:这张牌是什么牌? 解: 教授告知甲点数,告知乙花色 人物 已知 未知 甲 A 红桃.方块 Q 红桃.草色 4 红桃.黑桃.草色 J 黑桃 8 黑桃 2 黑桃 7 黑桃 3 黑

mysql 获取一张表中, 另一张表不存在的数据

编写sql语句中,经常需要编写获取一张数据表中不存在与另一张表的数据,相关编写方法如下: 方法1: 使用not in ,效率低下,在数据较小的情况下可以采用如下编写 SELECT * FROM a WHERE 1=1 AND a.Id NOT IN( SELECT Id FROM B WHERE B.IsDeleted=0 GROUP BY B.Id ); 方法2:使用left join  较第一种方法快 SELECT * FROM a LEFT JOIN b ON a.Id=b.Id WHER

mysql 从相同类型的多张表中提取到一张表中

蜗牛背着沉重的壳,贴着地面一步步艰难地向前爬行,不回头,也不左顾右盼,只是朝着自己想到达的地方行进. 有时候需要从多张相同类型的表中提取数据,这些表有一些相同的列或者表结构完全相同,同时表名存在一定的规律,如果表数量少还好,如果表数量多的话则会比较繁琐.可以通过存储过程将多张表的数据提取到一张表的方法来降低工作量. 先创建测试表并生成测试数据.以下存储过程创建10张测试表,每张表生成10条测试数据.drop PROCEDURE if EXISTS create10tables;create PR

MYSQL查询A表中不存在于B表中的所有符合条件的数据

在开发过程中,总有一些需求是需要查看在A表中ID不存在于B表中的ID的情况: 下面有三种方法可以实现这一需求: 第一种:使用Not in 方法通过子查询的结果集来做过滤: select * from A where 1=1 AND A.ID not in (select ID from B ) 这种情况最常见也是最容易理解的逻辑SQL代码,但是会有很多问题出现. 首先,这种情况是针对数据量比较小的情况使用的,原因在于IN 和 NOT IN并不是针对索引进行查询的,操作效率相对较慢.可以通过使用N

B表中的pid对应A表中id,查询A表中数据,根据b表中对应a表中该id的数据数目排序

select a.*,count(*) as c from a left join b on a.id=b.aid group by a.id ORDER BY c desc

Mysql将其他表中的数据更新到指定表中

update tb  set tb.字段= (select 字段 from tb1 where tb.字段1 = tb1.字段1); update role set uid = (select ID from users where role.name=name); 原文地址:https://www.cnblogs.com/change4now/p/8372220.html

取得一张表的数据不在另一张表中的最优秀方法(JOIN与EXISTS的效率研究)

业务需求: 公司有个CRM经纪人管理系统,前天遇到的比较棘手的问题是,要查询一张表中不在另一张表中的所有用户并分页显示,但问题是外表的数据量很大,如果用not in(select ..),not exists(select ...)之类的子查询 的话需要对子查询表进行所有信息的调用过滤才行,一单子查询数据量过大效率问题就来了,于是就私下里查了一点资料,并根据资料中提供的例子建立了对应的测试表做了一些测试,随后将解决问题的方法移交给了技术部的邹鸿同事去解决问题,因为是前天的事情了,本来是事情忙没时