上一節講了關係代數的一些基本運算,本節繼續講解其餘的基本運算:笛卡爾積和更名運算。
笛卡爾積(x)
笛卡爾積運算使得我們可以將任意兩個關係的信息組合在一起。
形式的說,R × S 被定義爲:
- R S = {r s| r R, s S}
- 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)
假設我們希望找出所有在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) ) )
這就是我們要查詢的結果。
其相應的查詢語句爲:
更名運算 (ρ)
更名運算的表達式是:ρ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)