SQL查询。exists和join之间的区别

SQL查询。exists和join之间的区别,sql,postgresql,select,join,exists,Sql,Postgresql,Select,Join,Exists,我有4张桌子: create table Product(pCode integer primary key, pName varchar(20), Color varchar(10); create table Cli(cCode integer primary key, cName varchar(20), city varchar(20)); create table Sale(pOut integer references Product(tCode), cOut integer ref

我有4张桌子:

create table Product(pCode integer primary key, pName varchar(20), Color varchar(10);
create table Cli(cCode integer primary key, cName varchar(20), city varchar(20));
create table Sale(pOut integer references Product(tCode), cOut integer references Client(cCode), countOut integer, dtOut date, primary key (pOut, kOut);
create table Buy (pIn integer references Product(pCode), cIn integer references Client(cCode), countIn integer, dtIn date, primary key (pIn, kIn);
我需要显示的客户名称不是来自喀山,而是那些在2015年上半年购买一些商品,然后在2015年下半年销售相同商品的客户

我通过使用视图解决了这个问题

create view vA as select cCode from Cli where Cli.City <> 'Kazan';
create view vB(cCode, pCode) as select cOut, pOut from Sale where '01.01.2015'<=dtOut AND dtOut<'01.07.2015';
create view vC(cCode, tCode) as select cIn, tIn where '01.07.2015<=dtIn AND dtIn < '01.01.2016';
create view vD as select * from vB inner join vC on vB.cKod=vC.cKod AND vc.pCode=vB.pCode;
create view vE as select * from vD  right outer join on vA on vA.cCode=vD.cCode;
create view vF as select distinct c.Knam from Cli as c inner join vE on vE.cCode=c.cCode;
对于vE-不存在而不是右外部联接:

create view vE as select * from vA where not exists(select * from vD where vA.cCode=vD.cCode);

我认为exists是一个更好的解决方案,因为常识告诉我它应该更快。如果您说exists,这意味着查询在找到匹配项时将停止,但如果您说notexist,则需要遍历所有元素以确保它不存在


我还想鼓励您使用更好的命名,因为现在查询很难阅读

这是最好使用

我的猜测是,您会发现优化器在内部连接和WHERE EXISTS之间选择了相同的方法,相反,右外部连接/为Null与不存在,因为它们在这个场景中大致相当,并且Postgres有一个很好的优化器

有人做了和你为vE查询做的完全相同的测试,他的结果是Postgres为这两个方法选择了一个哈希反连接


最后,如果你不确定哪条路线是最好的,那就把这两条都写下来,看看哪条效果最好。在查询运行后检查统计数据并查看解释。

如果可以在单个查询中轻松创建一组视图,为什么还要创建这些视图?您的代码很难理解,因为列名会切换,这使得提供更具体的建议变得更加困难。它们在逻辑上是不同的。从存在的位置选择*从任何表中选择任何内容都可以产生最多的carda行,而在可能涉及a和b的某些条件下,从联接b中选择*可以产生最多的carda*cardb记录,这可能大于carda。
create view vE as select * from vA where not exists(select * from vD where vA.cCode=vD.cCode);