上一节讲了关系代数的一些基本运算,本节继续讲解其余的基本运算:笛卡尔积和更名运算。


  

笛卡尔积x

笛卡尔积运算使得我们可以将任意两个关系的信息组合在一起。

形式的说,R × S 被定义为:

R  \times  S = { r  \cup  sr  \in  Rs  \in  S}

假设我们希望找出所有在Perryridge支行有贷款的客户姓名。

为了实现这一要求,我们同时需要关系loan和关系borrower中的信息。

σbranch_name="Perryridge"(borrower \times loan)

然而,customer_name列却可能包含在Perryridge支行没有贷款的客户。

因为笛卡尔积中保留了所有可能的由一个来自borrower的元组和一个来自loan的元组构成的元组对。

由于笛卡尔积运算将loan中的每个元组同borrower中的每个元组进行联系,而我们又知道如果客户在Perryridge支行有贷款,则borrower \times loan中必定存在某个元组,其中包含了该客户的姓名,并且borrwoer.loan_number=loan.loan_number

因此如果我们用下面的表达式就可以得到borrower \times loan中与在Perryridge支行有贷款的客户相关的所有元组。

σborrwoer.loan_number=loan.loan_number

(σbranch_name="Perryridge"(borrower \times loan) )

最后,由于我们只需要customer_name,我们进行投影:

πcustomer_name(σborrower.loan_number=loan.loan_number

(σbranch_name="Perryridge"(borrower \times loan) ) )

这就是我们要查询的结果。

其相应的查询语句为:


  
  1. mysql> select customer_name from borrower, loan 
  2.     -> where borrower.loan_number=loan.loan_number 
  3.     -> and branch_name="Perryridge"
  4. +---------------+ 
  5. | customer_name | 
  6. +---------------+ 
  7. | Hayes         | 
  8. | Admas         | 
  9. +---------------+ 
  10. 2 rows in set (0.00 sec) 

更名运算 (ρ)

更名运算的表达式是:ρ(E)

假设关系代数表达式En元的,则表达式

ρx(A1,A2……An(E)

返回表达式E的结果,并赋给它名字x,同时将各属性更名为A1,A2……An

1查询“找出银行中最大的账户余额”。

我们的策略是:

(1)    首先计算出一个由非最大的余额构成的临时关系;

(2)    计算关系πbalance (account)和刚才算出的临时关系之间的集合差。

步骤一:为了计算该临时关系,我们需要比较所有账户余额的值。要做这样的比较,我们可以通过笛卡尔积account ×account并构造一个选择来比较任意两个出现在同一元组中的余额。

πaccount.balance (σacount.balance<d.balance (account×ρd (account) ) )

其相应的查询语句为:

步骤二:查找银行中最大余额的查询:

πbalance(account) -

πaccount.balance(σacount.balance<d.balance (account×ρd (account)))

 

其相应的查询语句为:


  
  1. mysql> select balance from account 
  2.     ->  where balance not in 
  3.     -> (select distinct account.balance from account, account d 
  4.     -> where account.balance<d.balance); 
  5. +---------+ 
  6. | balance | 
  7. +---------+ 
  8. |     900 | 
  9. +---------+ 
  10. 1 row in set (0.00 sec) 

2:查询“找出所有与Smith居住在同一城市同一街道的客户”

首先得到Smith居住的城市和街道:

πcustomer_street, customer_city(σcustomer_name= "Smith " (customer) )

其相应的查询语句为:


  
  1. mysql> select customer_street, customer_city 
  2.     -> from customer 
  3.     -> where customer_name="Smith"
  4. +-----------------+---------------+ 
  5. | customer_street | customer_city | 
  6. +-----------------+---------------+ 
  7. | North           | Rye           | 
  8. +-----------------+---------------+ 
  9. 1 row in set (0.00 sec) 

为了找出居住在这个城市这条街道的其它客户,我们必须再次引用customer关系。现在对上面的表达式进行更名运算,给此表达式的结果以名字smith_addr,并将其属性更名为streetcity,替换原有的customer_streetcustomer_city:

πcustomer.customer_name

(σcustomer.customer_street=smith_addr.streetcustomer_city=smith_addr.city

(customer×ρsmith_addr(street,city)

πcustomer_street, customer_city(σcustomer_name= "Smith " (customer)))))

其相应的查询语句为:


  
  1. mysql> select customer.customer_name from customer, 
  2.     -> (select customer_street street, customer_city city 
  3.     ->   from customer 
  4.     ->   where customer_name="Smith") smith_addr 
  5.     -> where customer.customer_street=smith_addr.street and 
  6.     -> customer_city=smith_addr.city; 
  7. +---------------+ 
  8. | customer_name | 
  9. +---------------+ 
  10. | Curry         | 
  11. | Smith         | 
  12. +---------------+ 
  13. 2 rows in set (0.00 sec)