如何在SQL中表示关系除法(基本代数表达式)

3

查询: 查找已预订所有船只的水手姓名

可以使用关系代数表示为:
1. πsname ( ((σsid,bid Reserves) / (σbid Boats)) ⋈ Sailors)

根据关系代数,也可以使用基本代数运算符表示除法,如下所示:

  1. A/B= πx(A) - πx((πx(A) * B) - A )

因此,如果我将语句1转换为语句2,则

  1. Reserves/Boats= πsid(Reserves) - πsid(( πbid(Reserves) * Boats) - Reserves )

我如何使用 SQL 表示语句3,并且要与关系代数中的方式相同(即不使用除了minus/Except(-) and Cross join(*)以外的任何操作符)。 我尝试在不使用NOT EXISTS 和 EXISTS条件的情况下实现它。

表的模式如下:
Sailors(sid: integer, sname: string, rating: integer, age: real)
Boats(bid: integer, bname: string, color: string)
Reserves(sid: integer, bid: integer, day: date)


1
如果您能构建一个SQLFiddle,并填充您想要使用的数据,同时提供您期望的结果,那将非常有帮助。请参考“如何提出好问题”(http://stackoverflow.com/help/how-to-ask)。谢谢。 - Bob Jarvis - Слава Україні
1
https://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/ - shawnt00
2个回答

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

假设这是与您相关的关系对应的表的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的原因。在查询中战略性地应用Distinct选择可能使其更有效,但不会改变结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接