3

最終試験では、かなり厄介な SQL、リレーショナル代数、リレーショナル微積分クエリを取得しました。私はこのクエリを得ました:

カテゴリ「コンピュータ」のすべての製品を注文したクライアントの名前を見つけます。(パソコンカテゴリー全商品ご注文のお客様)

スキーマは次のとおりです。

顧客 ( Customer_Id、Cust_First_Name、Cust_Last_Name)

注文 ( Order_Id , *Customer_Id*)

Order_items ( Order_Item_id , *Order_Id*, *Product_Id*)

Product_info ( Product_Id、 Product_Name 、 Category)

ボールド (主キー)、イタリック (外部キー)

このクエリをリレーショナル代数に変換するには、サブクエリではなく結合を使用する必要があります。少し自分を助けるために、まず SQL を書き、次に SQL クエリをリレーショナル代数に変換します。

ここに私の試みがあります:

1を試してください(サブクエリを使用):

select C.Customer_Id
from Customer C
where
(
select count(*)
from product_info
where category = 'Computer'
)=(select count (distinct pi.Product_id)
from orders S, order_items OI, product_info pi
where S.Customer_Id = C.Customer_Id and S.Order_Id = OI.Order_Id and  pi.product_id=OI.product_id and category = 'Computer')

2 を試してください (having 句で 1 つのサブクエリを使用):

select C.Customer_Id
from Customer C, Product_info pi, Orders S, Order_Items oi
where C.Customer_Id = S.Customer_Id and S.Order_Id = OI.Order_Id and OI.Product_Id = pi.Product_Id and pi.category = 'Computer'
group by C.Customer_Id
having count (distinct pi.Product_Id) = 
(
select count (*) 
from Product_info
where category = 'Computer'
)

3 を試してください (from 句のサブクエリ):

select C.Customer_Id
from Customer C, Product_info pi, Orders S, Order_Items oi,
(
select count (*) num
from Product_info
where category = 'Computer'
) numbr
where C.Customer_Id = S.Customer_Id and S.Order_Id = OI.Order_Id and OI.Product_Id = pi.Product_Id and pi.category = 'Computer'
group by C.Customer_Id, numbr.num
having count (distinct pi.Product_Id) = numbr.num

現在、このクエリは関係代数で表すことができますが、値が重複するため非効率的です。

私の最後の試み(これはコンパイルせず、どこでサブクエリを使用します):

select *
from Customer C
where not exists
(select *
from (select Order_Id from orders O where O.Customer_Id = C.Customer_Id) S INNER JOIN order_items OI on S.Order_Id = OI.Order_Id
RIGHT OUTER JOIN (select Product_Id from product_info where category ='Computer') PI on PI.Product_Id = OI.Product_Id
where OI.Product_Id = null)

この場合、LATERALを使用できるとどこかで読みましたが、LATERALに関する情報がほとんどないため、正しく理解できませんでした。

試験は終わりましたが、解決策についてはまだ興味があります。この 6 つのクエリ、ER ダイアグラム、ER-To-Relational、BCNF への正規化、3NF を含む 2 時間の試験だったので、このクエリを解決するのがいかに難しいかが頭に浮かびます。ここで重要な何かが欠けていますか?

これは私を少し助ける小さなサンプルデータです:

http://pastebin.com/DkCe0AGm

前もって感謝します。

4

2 に答える 2

2

これは、関係代数の除算演算子を使用すると非常に簡単です。関係代数で記述できるものはすべて SQL で記述できるからといって、関係代数で記述できるものはすべて SQL でも同じように記述できるという意味ではないことに注意してください。SQL には除算演算子に相当する簡単なものがないため、最初にこれを SQL で記述しようとしても役に立ちません。

ここでギリシャ文字を書く方法がわからないので、いくつか書き出すだけにします。

シグマ ->
Pi を選択 ->
Rho をプロジェクト -> 名前を変更

PROJECT c.Cust_First_Name, c.Cust_Last_Name, i.Product_ID (SELECT c.customer_id = o.customer_id, o.order_id = i.order_id (RENAME (Customer c) X RENAME (Orders o) X RENAME (Order_items i))) 
DIVIDE PROJECT p.product_id (SELECT p.category = 'Computers' (RENAME (Products p)))

これを LaTeX エディターに入力すると、実際の形式で表示されます。

\Pi_{c.cust\_last\_name, c.cust\_first\_name, i.product\_id} (\sigma_{c.customer\_id = o.customer\_id, o.order\_id = i.order\_id}(\rho_{c}(customer) X \rho_{o}(orders) X \rho_{i}(order\_items))) 
\div  \Pi_{p.product\_id}(\sigma_{p.category='computers'}(\rho_{p}(products)))

これはサブクエリであると主張することもできますが、2 つの異なるクエリであると言えます。

于 2012-06-22T16:17:32.860 に答える
1

質問があいまいです。このバージョンでは、カテゴリ コンピューターからの製品のみを注文した顧客を取得します。

select c.customer_id, c.Cust_First_Name, c.Cust_Last_Name
from Customer c join
     Orders o
     on c.customer_id = o.customer_id join
     Order_Item oi
     on o.order_Id = oi.order_id join
     Product_Info pi
     on oi.Product_id = pi.product_id
group by c.customer_id, c.Cust_First_Name, c.Cust_Last_Name
having min(case when pi.category = 'Computer' then 1 else 0 end) = 1

この場合、顧客がカテゴリで購入していない製品を持っているかどうかを数えているだけです。

もう 1 つの解釈は、「コンピューター カテゴリのすべての製品を注文した顧客」です。

select c.customer_id, c.Cust_First_Name, c.Cust_Last_Name
from Customer c join
     Orders o
     on c.customer_id = o.customer_id join
     Order_Item oi
     on o.order_Id = oi.order_id join
     Product_Info pi
     on pi.Product_id = oi.Product_id cross join
     (select count(distinct product_id) as cnt
      from Product_info pi
      where category = 'Computer'
     ) comps
where pi.Category = 'Computer'
group by c.customer_id, c.Cust_First_Name, c.Cust_Last_Name
having count(distinct product_id) = comps.cnt

この場合の考え方は、個別の製品の数を数え、数が一致するかどうかを確認することです。

これらをリレーショナル代数に変換することが実際に適切なクエリを形成するのに役立つかどうかはわかりません。

于 2012-06-22T15:04:16.757 に答える