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

问题描述 投票:0回答:3

Query:
查找预订了所有船只的水手姓名

这可以用关系代数表示为:
1.

πsname ( ((σsid,bid Reserves) / (σbid Boats))  ⋈ Sailors)

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

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

因此,如果我

convert
声明
1
按照声明
2
那么

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

我如何用 SQL 表示

Statement 3
,就像在关系代数中一样(即不使用
minus/Except(-) and Cross join(*)
以外的任何运算符)。
我试图在不使用
NOT EXISTS and EXISTS
条件的情况下实现它。

表结构如下:

Sailors
(sid:整数,sname:字符串,评级:整数,年龄:真实)
Boats
(出价:整数,bname:字符串,颜色:字符串)
Reserves
(sid:整数,bid:整数,day:日期)

sql oracle relational-algebra relational-division
3个回答
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
的原因。在查询的其他地方战略性地应用不同的选择可能会提高效率,但不会改变结果。


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

您可以在这里测试:

示例


0
投票

编写SQL语句和关系代数表达式进行检索 居住在墨西哥的所有客户的 CustomerID、ContactName。分配 结果到关系代数表达式中带有您全名的变量

© www.soinside.com 2019 - 2024. All rights reserved.