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

时间:2015-09-30 14:06:00

标签: sql oracle relational-algebra relational-division

Query:找到保留所有船只的水手的名字

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

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

  1. A/B= πx(A) - πx((πx(A) * B) - A )
  2. 因此,如果convert声明1符合声明2那么

    1. Reserves/Boats= πsid(Reserves) - πsid(( πbid(Reserves) * Boats) - Reserves )
    2. 我如何以与在关系代数中相同的方式用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:整数,日期:日期)

2 个答案:

答案 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

你可以在这里测试一下:

Example

答案 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 JOINMINUS操作,以便直接对应于关系代数公式。但是,在真实世界的数据库应用程序中,人们肯定会通过完全不同的查询获得相同的结果。

另请注意,SQL数据库可以并且确实违反了正式关系代数的原则,即关系不包含重复元组。这就是第一个子查询中SELECT DISTINCT的原因。在查询的其他地方策略性地应用的不同选择可能会使其更有效,但不会改变结果。