上一节讲了关系代数的一些基本运算,本节继续讲解其余的基本运算:笛卡尔积和更名运算。
笛卡尔积(x)
笛卡尔积运算使得我们可以将任意两个关系的信息组合在一起。
形式的说,R × S 被定义为:
假设我们希望找出所有在Perryridge支行有贷款的客户姓名。
为了实现这一要求,我们同时需要关系loan和关系borrower中的信息。
σbranch_name="Perryridge"(borrower loan)
然而,customer_name列却可能包含在Perryridge支行没有贷款的客户。
因为笛卡尔积中保留了所有可能的由一个来自borrower的元组和一个来自loan的元组构成的元组对。
由于笛卡尔积运算将loan中的每个元组同borrower中的每个元组进行联系,而我们又知道如果客户在Perryridge支行有贷款,则borrower loan中必定存在某个元组,其中包含了该客户的姓名,并且borrwoer.loan_number=loan.loan_number。
因此如果我们用下面的表达式就可以得到borrower loan中与在Perryridge支行有贷款的客户相关的所有元组。
σborrwoer.loan_number=loan.loan_number
(σbranch_name="Perryridge"(borrower loan) )
最后,由于我们只需要customer_name,我们进行投影:
πcustomer_name(σborrower.loan_number=loan.loan_number
(σbranch_name="Perryridge"(borrower loan) ) )
这就是我们要查询的结果。
其相应的查询语句为:
- mysql> select customer_name from borrower, loan
- -> where borrower.loan_number=loan.loan_number
- -> and branch_name="Perryridge";
- +---------------+
- | customer_name |
- +---------------+
- | Hayes |
- | Admas |
- +---------------+
- 2 rows in set (0.00 sec)
更名运算的表达式是:ρx (E)
假设关系代数表达式E是n元的,则表达式
ρ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)))
其相应的查询语句为:
- mysql> select balance from account
- -> where balance not in
- -> (select distinct account.balance from account, account d
- -> where account.balance<d.balance);
- +---------+
- | balance |
- +---------+
- | 900 |
- +---------+
- 1 row in set (0.00 sec)
例2:查询“找出所有与Smith居住在同一城市同一街道的客户”
首先得到Smith居住的城市和街道:
πcustomer_street, customer_city(σcustomer_name= "Smith " (customer) )
其相应的查询语句为:
- mysql> select customer_street, customer_city
- -> from customer
- -> where customer_name="Smith";
- +-----------------+---------------+
- | customer_street | customer_city |
- +-----------------+---------------+
- | North | Rye |
- +-----------------+---------------+
- 1 row in set (0.00 sec)
为了找出居住在这个城市这条街道的其它客户,我们必须再次引用customer关系。现在对上面的表达式进行更名运算,给此表达式的结果以名字smith_addr,并将其属性更名为street和city,替换原有的customer_street和customer_city:
πcustomer.customer_name
(σcustomer.customer_street=smith_addr.street∧customer_city=smith_addr.city
(customer×ρsmith_addr(street,city)
πcustomer_street, customer_city(σcustomer_name= "Smith " (customer)))))
其相应的查询语句为:
- mysql> select customer.customer_name from customer,
- -> (select customer_street street, customer_city city
- -> from customer
- -> where customer_name="Smith") smith_addr
- -> where customer.customer_street=smith_addr.street and
- -> customer_city=smith_addr.city;
- +---------------+
- | customer_name |
- +---------------+
- | Curry |
- | Smith |
- +---------------+
- 2 rows in set (0.00 sec)