3.15 考虑图3-19中的银行数据库,其中加下划线的是主码。为这个关系数据库构造出如下SQL查询:
a.找出在"Brooklyn"的所有支行都有账户的所有客户。
这个银行数据库咱们在习题3.8中已经创建了。当时咱们创建的所有支行数据所在地都是北京。这样题目中提到的所在地咱们使用北京。
这样我们先找出在北京的某个支行有账户的所有客户:
select customer_name, branch_name from depositor
natural join account natural join branch
where branch_city = '北京';
结果如下:
customer_name | branch_name
---------------+-------------
客户_1 | 银行支行_1
客户_1 | 银行支行_2
客户_2 | 银行支行_3
客户_3 | 银行支行_3
客户_4 | 银行支行_4
客户_5 | 银行支行_1
客户_6 | 银行支行_1
客户_7 | 银行支行_4
客户_8 | 银行支行_4
(9 rows)
从上面结果看,没有任何客户拥有北京的所有支行的账户,这样为了后面能有查询结果,我们给客户_1在银行支行_3, 4分别再创建两个账户吧:
insert into account values ('账户_10', '银行支行_3');
insert into account values ('账户_11', '银行支行_4');
insert into depositor values ('客户_1', '账户_10');
insert into depositor values ('客户_1', '账户_11');
再次查询最开始的SQL,结果如下:
customer_name | branch_name
---------------+-------------
客户_1 | 银行支行_1
客户_1 | 银行支行_2
客户_2 | 银行支行_3
客户_3 | 银行支行_3
客户_4 | 银行支行_4
客户_5 | 银行支行_1
客户_6 | 银行支行_1
客户_7 | 银行支行_4
客户_8 | 银行支行_4
客户_1 | 银行支行_3
客户_1 | 银行支行_4
(11 rows)
这样客户_1就拥有的所有支行的账户,接下来我们以这些关系建立一个临时关系customer_branch:
with customer_branch(customer_name, branch_name) as (
select customer_name, branch_name from depositor
natural join account natural join branch
where branch_city = '北京'
)
然后我们再创建一个临时关系branch_name_beijing,这个关系保存着北京的所有支行名称:
with branch_name_beijing(branch_name) as (
select branch_name from branch where branch_city = '北京'
)
如果一个客户在北京的所有支行中都有账户,也就是说cutomer_branch关系中的某个customer_name的对应的branch_name组成的集合应该是关系branch_name_beijing的列branch_name组成的集合的子集,也就是说后一个集合减去前一个集合,值应该为空,那么查询应该如下:
with customer_branch(customer_name, branch_name) as (
select customer_name, branch_name from depositor
natural join account natural join branch
where branch_city = '北京'
), branch_name_beijing(branch_name) as (
select branch_name from branch where branch_city = '北京'
)
select distinct customer_name
from customer_branch as S
where not exists (
(select branch_name from branch_name_beijing)
except
(select branch_name from customer_branch where customer_name = S.customer_name)
);
customer_name
---------------
客户_1
(1 row)
b.找出银行的所有贷款额的总和。
select branch_name, sum(amount) from loan group by branch_name;
branch_name | sum
-------------+----------
银行支行_3 | 410.00
银行支行_4 | 12484.00
银行支行_2 | 45.00
银行支行_1 | 583.00
(4 rows)
c.找出总资产至少比位于Brooklyn的某一家支行要多的所有支行名字。
select * from branch;
branch_name | branch_city | assets
-------------+-------------+----------
银行支行_1 | 北京 | 66666.00
银行支行_2 | 北京 | 77777.00
银行支行_3 | 北京 | 88888.00
银行支行_4 | 北京 | 99999.00
(4 rows)
从结果看,银行支行_1的资产最少,那么查询结果也应该是其他3个支行,我们执行我们所写的SQL语句吧:
select branch_name from branch
where assets > some(
select assets from branch where branch_city = '北京'
);
branch_name
-------------
银行支行_2
银行支行_3
银行支行_4
(3 rows)