Query:
找到保留所有船只的水手的名字
这可以用关系代数表示为:
1. πsname ( ((σsid,bid Reserves) / (σbid Boats)) ⋈ Sailors)
根据关系代数,也可以使用基本代数运算符表示除法如下:
A/B= πx(A) - πx((πx(A) * B) - A )
因此,如果convert
声明1
符合声明2
那么
Reserves/Boats= πsid(Reserves) - πsid(( πbid(Reserves) * Boats) - Reserves )
我如何以与在关系代数中相同的方式用SQL表示Statement 3
(即不使用minus/Except(-) and Cross join(*)
以外的任何运算符)。
我试图在不使用NOT EXISTS and EXISTS
条件的情况下实现它。
表的模式如下:
Sailors
(sid:integer,sname:string,rating:integer,age:real)
Boats
(出价:整数,bname:字符串,颜色:字符串)
Reserves
(sid:整数,bid:整数,日期:日期)
答案 0 :(得分:1)
查询将是:
select
sailors.sname
from (
select r.sid
from reserves r
group by r.sid
having count(distinct r.bid) = (select count(*) from boats) ) fullRes
join sailors
on sailors.sid = fullRes.sid
你可以在这里测试一下:
答案 1 :(得分:1)
给定与您的相关关系相对应的表的DDL:
create table Boats(
bid int,
bname varchar(50),
color varchar(50)
);
create table Reserves(
sid int,
bid int,
day date
);
您可以相当直接地将除式公式(3)音译为Oracle SQL语法,尽管它很详细:
-- All sailors who reserved at least one boat
SELECT DISTINCT sid
FROM Reserves
MINUS
-- All sailors who reserved at least one boat, but not all of them
SELECT sid
FROM (
-- all combinations of a sailor who reserved any boat with any boat
-- available to be reserved:
SELECT Reserves.sid, Boats.bid
FROM
Reserves
CROSS JOIN
Boats
MINUS
-- all combinations of sailor and boat for actual reservations made
SELECT sid, bid
FROM Reserves
) sids
根据规定,它仅使用CROSS JOIN
和MINUS
操作,以便直接对应于关系代数公式。但是,在真实世界的数据库应用程序中,人们肯定会通过完全不同的查询获得相同的结果。
另请注意,SQL数据库可以并且确实违反了正式关系代数的原则,即关系不包含重复元组。这就是第一个子查询中SELECT DISTINCT
的原因。在查询的其他地方策略性地应用的不同选择可能会使其更有效,但不会改变结果。