理解此查询真的很难

时间:2015-10-11 04:47:51

标签: mysql sql nested-queries

以下查询应该返回“保留所有船只的水手”

这是mySQL代码

SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS 
    ((SELECT B.bid  
     FROM Boats B)
    Except
    (SELECT R.bid  
     FROM Reserves R
     WHERE R.sid = S.sid))

我只是......不知道如何阅读它。我知道“NOT EXISTS”后面的子查询应返回Boats表中所有记录的船ID(bid)。因此,接下来的查询应该返回所有已预留的船只的船只ID ...这意味着如果有人保留所有船只,则不应返回任何内容,这意味着NOT EXISTS将评估为真,它将只是给那个水手的名字?我认为这是让我困惑的最后一部分...它最终如何归还水手的名字?

2 个答案:

答案 0 :(得分:1)

我们有一些可以由水手保留的船只,水手已经注册并且我们知道它们,所以表格的结构是:

[Table: Boats]          [Table: Sailors]        [Table: Reserves]
+-----+--------+        +-----+----------+      +-----+-----+-----+
| bid | bname  |        | sid | sname    |      | rid | bid | sid |
+-----+--------+        +-----+----------+      +-----+-----+-----+
| 1   | Boat 1 |        | 1   | Sailor 1 |      | 1   | 1   | 1   |
| 2   | Boat 2 |        | 2   | Sailor 2 |      | 2   | 2   | 3   |
| 3   | Boat 3 |        | 3   | Sailor 3 |      +-----+-----+-----+
+-----+--------+        +-----+----------+

在上述数据中,您需要知道哪些船没有预留;您可以使用以下查询,为您提供出价=> 3:

SELECT B.bid  FROM Boats B
EXCEPT
SELECT R.bid  FROM Reserves R;

当你需要知道水手没有(永远)保留哪些船只时;您可以使用以下查询,为您提供出价=> [1,3]为sid = 3:

SELECT B.bid  FROM Boats B
EXCEPT
SELECT R.bid  FROM Reserves R  WHERE R.[sid] = 3;

当水手预留所有船只时,上述查询将无效,因此NOT EXISTS(<above query>)将成立。现在你可以使用上面的查询找到保留所有船只的水手:

SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS (
    SELECT B.bid  FROM Boats B
    EXCEPT
    SELECT R.bid  FROM Reserves R
    WHERE R.[sid] = S.[sid]);

所以如果Reserves的数据变成这样:

 [Table: Reserves]
 +-----+-----+-----+
 | rid | bid | sid |
 +-----+-----+-----+
 | 1   | 1   | 1   |
 | 2   | 2   | 1   |
 | 3   | 3   | 1   |
 +-----+-----+-----+

您的查询会得到Sailor 1;)的结果。

更多信息:
EXCEPT 会返回左输入查询中不是由右输入查询输出的不同行。
EXISTS :指定要测试行是否存在的子查询。

答案 1 :(得分:0)

您可以转换sql,即子选择

(SELECT B.bid  
 FROM Boats B)
Except
(SELECT R.bid  
 FROM Reserves R
 WHERE R.sid = S.sid)

应与

相同
(SELECT B.bid  
 FROM Boats B
 WHERE B.sid <> S.sid)

如果你替换主sql中的部分,你得到

SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS 
(SELECT B.bid  
 FROM Boats B
 WHERE B.sid <> S.sid)

仅选择那些没有其他sid的船只的水手,这与那些预留了所有船只的船员相同#34;