【发布时间】:2016-04-25 03:26:55
【问题描述】:
我有 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;
如果我要使用 join exists / not exists 会有所不同吗?
例如对于 vD - 存在而不是内部连接:
create view vD as select * from vB where exists(select * from vC where B.cCode=vC.cCode AND vc.pCode=vB.pCode);
对于 vE - 不存在而不是右外连接:
create view vE as select * from vA where not exists(select * from vD where vA.cCode=vD.cCode);
【问题讨论】:
-
当您可以轻松地在单个查询中执行此操作时,为什么还要创建一堆视图?您的代码很难遵循,因为列名会切换,这使得提供更具体的建议变得更加困难。
-
它们在逻辑上是不同的。
SELECT * FROM a WHERE EXISTS (SELECT anything from any table)最多可以产生 card(a) 行,而SELECT * FROM a JOIN b ON (some condition possibly involving a and b)最多可以产生 card(a) * card(b) 记录,可能比 card(a) 大。
标签: sql postgresql select join exists