如何用 SQL 表示关系除法(基本代数表达式)
How to represent relational division(basic algebra expression) in terms of SQL
Query:
查找已预订所有船只的水手姓名
这可以用关系代数表示为:
1. π<sub>sname</sub> ( ((σ<sub>sid,bid</sub> 储备) / (σ<sub>bid</sub> 船)) ⋈ 水手)
根据关系代数,除法也可以使用基本代数运算符表示如下:
A/B= π<sub>x</sub>(A) - π<sub>x</sub>((π<sub>x</sub>(A) * B) - A )
因此,如果我 convert
根据声明 2
声明 1
,则
Reserves/Boats= π<sub>sid</sub>(保留) - π<sub>sid</sub>(( π<sub>出价</sub>(储备)*船)-储备)
我如何用 SQL 表示 Statement 3
,就像在关系代数中一样(即不使用 minus/Except(-) and Cross join(*)
以外的任何运算符)。
我试图在不使用 NOT EXISTS and EXISTS
条件的情况下实现它。
表格架构如下:
Sailors
(sid: 整数, sname: 字符串, 评分: 整数, 年龄: 真实)
Boats
(bid: integer, bname: string, color: string)
Reserves
(sid: 整数, bid: 整数, day: 日期)
查询将是:
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
你可以在这里测试:
给定与您的相关关系对应的表的此 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
的原因。在查询的其他地方有策略地应用不同的选择可能会提高效率,但不会改变结果。
Query:
查找已预订所有船只的水手姓名
这可以用关系代数表示为:
1. π<sub>sname</sub> ( ((σ<sub>sid,bid</sub> 储备) / (σ<sub>bid</sub> 船)) ⋈ 水手)
根据关系代数,除法也可以使用基本代数运算符表示如下:
A/B= π<sub>x</sub>(A) - π<sub>x</sub>((π<sub>x</sub>(A) * B) - A )
因此,如果我 convert
根据声明 2
声明 1
,则
Reserves/Boats= π<sub>sid</sub>(保留) - π<sub>sid</sub>(( π<sub>出价</sub>(储备)*船)-储备)
我如何用 SQL 表示 Statement 3
,就像在关系代数中一样(即不使用 minus/Except(-) and Cross join(*)
以外的任何运算符)。
我试图在不使用 NOT EXISTS and EXISTS
条件的情况下实现它。
表格架构如下:
Sailors
(sid: 整数, sname: 字符串, 评分: 整数, 年龄: 真实)
Boats
(bid: integer, bname: string, color: string)
Reserves
(sid: 整数, bid: 整数, day: 日期)
查询将是:
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
你可以在这里测试:
给定与您的相关关系对应的表的此 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
的原因。在查询的其他地方有策略地应用不同的选择可能会提高效率,但不会改变结果。