用SQL语句表示除法操作
首先,定义我们要使用的三张表。
1.CREATE TABLE depositor( customer_name CHAR(20), account_number CHAR(10), PRIMARY KEY(customer_name, account_number) )
2.CREATE TABLE account( account_number CHAR(10), branch_name CHAR(15), balance NUMERIC(12,2) PRIMARY KEY(account_number) )
3.CREATE TABLE branch( branch_name CHAR(15), branch_city CHAR(30), assets NUMERIC(16,2) PRIMARY KEY(branch_name) )
有了这三张表之后,来看我们的问题。
“Find all customers who have an account count at all the branches located in Brooklyn”
翻译过来的意思就是找到在Brooklyn的所有支行,都有账户的客户。
我们先把答案写在这里:
SELECT DISTINCT S.customer_name FROM depositor as S WHERE NOT EXISTS ((SELECT branch_name FROM branch WHERE branch_city = ‘Brooklyn’) EXCEPT (SELECT R.branch_name FROM depositor as T, account as R WHERE T.account_number = R.account_number AND S.customer_name = T.customer_name))
这就是用SQL语句实现的一个简单除法操作。
我们把问题一个一个分开来解释:
1.
我们能看到这个查询在主查询中用到了depositor表。而在它的嵌套子查询中,同样用到了这张表。所以,这个查询为相关子查询。
相反,如果这个嵌套查询在子查询中没有用到主查询中的表,那么我们称之为无关子查询。
相关子查询和无关子查询的在使用上的区别是什么呢?如果一个嵌套查询中包含无关子查询。那么我们会先执行子查询,在子查询结果的这张表中,我们再执行主查询。也就是说在子查询结果的基础之上再进行查询。
而相关子查询不同,在主查询中扫描一条记录,比如果我们拿到了一条depositor的记录A,我们会把A带入到子查询中,看结果是否为真,如果为真,那么就输出A。然后取depositor的表中的下一项B。一次逐条扫描。
2.
在数据库中,如果我们想表示关系A包含关系B。我们应该怎么表示呢?
对!用NOT EXISTS关键字。
如果我们说A包含B,那么也就等价于NOT EXISTS ( B EXCEPT A)
换句话说就是 ==》不存在属于B而不属于A的元组。那么也就是A包含B。
现在再看我们的答案。显然清晰多了。
操作B:
SELECT branch_name FROM branch WHERE branch_city = ‘Brooklyn’
执行的结果是:找到地点在Brooklyn的所有支行。
操作A:
SELECT R.branch_name FROM depositor as T, account as R WHERE T.account_number = R.account_number AND S.customer_name = T.customer_name
执行的结果是:客户S.1有账户的所有支行。
现在如果A的结果包含B的结果,也就是说一个客户它所有有账户的支行包括了地点在Brooklyn的所有支行,那么我们就把客户S.1输出出来,再去扫描S.2。同理,结果为真就进行输出,结果为假就去扫描下一条记录,直到这个表的结束。这样我们就得到了我们想要的结果。