SQL:找到至少预留了两艘船的水手的名字

时间:2017-05-23 20:02:37

标签: sql oracle

问题

考虑一下表:

sailors (sid, sname, rating, age)
boats (bid, bname, color)
reserves (sid, bid, date)

找到至少预留两艘船的水手的名字。

我的方法

select s.sid,count(b.bid) 
from sailors s, reserves r
where s.sid=r.sid 
group by r.sid 
having count(r.bid) > = 2

我在这个查询中得到了答案。

但答案给出了

SELECT sname
FROM s, r r1, r r2
WHERE s.sid=r1.sid 
  AND s.sid=r2.sid 
  AND r1.bid<>r2.bid 

两者都给出了相同的答案,但我只是想知道它实际运作的顺序;关联性。

请帮帮我。

2 个答案:

答案 0 :(得分:1)

你的方法还不远,但你真的应该使用EXPLICIT连接语法,除非RDBM不支持它,但看到它已超过20年作为它应该的标准。

select
    s.sid, count(DISTINCT r.bid) as NumberOfBoats
from
    sailors s
    INNER JOIN reserves r
    ON s.sid = r.sid 
group by
    s.sid 
having
    count(DISTINCT r.bid) > = 2

您遇到的一个问题是,您所计算的所有投标保留都不是唯一的出价,这意味着如果他们多次租用同一条船,那么该记录仍将被退回。您想使用DISTINCT r.bid来查找租用超过1艘船的水手。

答案 1 :(得分:0)

第一个声明可以回答问题,因为它总结了每个水手的出价数量,然后保留了计数大于或等于2的记录。

第二个陈述推断出答案。要做到这一点,它会匹配每个水手和他们的出价之间的所有关系两次,并将每组关系命名为两个不同的表。最后,通过比较其中一个中与每个水手相关的出价,以及与另一个表<中相同水手相关的出价,将这些记录保存在水手有多个出价的地方/ em>的。要更清楚地看到这一点,请在选择中将sname替换为*,然后您将看到字段如何重复。

然而,此声明将返回n*n-n结果,因为它不询问出价数量,而是询问两个出价(针对同一水手)的不同之处。因此,如果在进行匹配时最初有3个不同的出价(a,b和c),则会找到具有以下不同出价的相同水手:a&lt;&gt; b,b&lt;&gt; a,a&lt;&gt; c,c&lt;&gt; a,b&lt;&gt; c和c&lt;&gt;一个。 正如您所看到的那样,答案是不确定的,因为至少有一个差异意味着至少有2个出价。