来自this网站:
表:
CREATE TABLE PilotSkills
(pilot_name CHAR(15) NOT NULL,
plane_name CHAR(15) NOT NULL,
PRIMARY KEY (pilot_name, plane_name));
CREATE TABLE Hangar
(plane_name CHAR(15) NOT NULL PRIMARY KEY);
查询:
SELECT DISTINCT pilot_name
FROM PilotSkills AS PS1
WHERE NOT EXISTS
(SELECT *
FROM Hangar
WHERE NOT EXISTS
(SELECT *
FROM PilotSkills AS PS2
WHERE (PS1.pilot_name = PS2.pilot_name)
AND (PS2.plane_name = Hangar.plane_name)));
我理解它用于(设置分区)的问题,包括将其描述为“这个机库中没有飞机我不能飞行!”的类比。我不明白的是这里的工作原理是什么,以及它如何结合起来做它所说的。
目前难以说明我的困难......
编辑:让我先问一下这样的事情,完全:
SELECT DISTINCT pilot_name
FROM PilotSkills
WHERE NOT EXISTS
(SELECT *
FROM Hangar)
我想我在这里缺少一些基本的理解......
编辑:不相关,没有第三个嵌套的SELECT就没有意义,对吧?
答案 0 :(得分:1)
最初作为次要评论,在这种情况下,选择*是过度的。您应该选择单个列或几列,但应避免拉出所有列,尤其是在子查询中,它们仅在查询期间使用而不在最终结果集中返回。也就是说,试图打破工作流程:
将其描述为双重否定(来自另一个答案)是理解它的好方法。它可以更直接地实现。
答案 1 :(得分:1)
我们想要的是一个独特的飞行员名单,可以在悬挂的每架飞机上飞行。为了实现这一点,对于一个特定的飞行员来说,不存在他们无法飞行的飞机。因此,我们希望获得每个飞行员的所有飞机的列表,看看是否有一架飞机无法飞行。如果有一个(飞行员不能飞行),我们将其从列表中删除。无论谁离开,都可以悬挂在衣架上的所有飞机。
更正式地说,找到一个明确的飞行员名单,这样对于一个给定的飞行员来说,在这组飞机中没有一架飞机(衣架),这样飞机就不存在于给定飞行员技能的集合中
“找到一份独特的飞行员名单 名...“
Select Distinct pilot_name
From PilotSkills As PS1
...
“......对于一个特定的飞行员来说,那里 在该组中不存在飞机 飞机(衣架)......“
Select Distinct pilot_name
From PilotSkills As PS1
Where Not Exists (
Select 1
From Hanger
“......这样飞机就不存在了 在给定飞行员的集合中 技巧“。
Select Distinct pilot_name
From PilotSkills As PS1
Where Not Exists (
Select 1
From Hanger As H
Where Not Exists (
Select 1
From PilotSkills As PS2
Where PS2.pilot_name = PS1.pilot_name
And PS2.plane_name = H.plane_name
)
)
答案 2 :(得分:0)
从概念上讲,这只是一个双重否定。
选择那里的所有飞行员 在机库中不存在飞机 他们不能飞。
但是你似乎在询问查询本身的机制?它使用两级相关子查询。
如果我们将行数减少到最小量并添加一个额外的表以稍微简化说明(查询中的PilotSkills的外部实例仅用于获取Pilots列表)。然后查询看起来像
SELECT pilot_name
FROM Pilots
WHERE NOT EXISTS
(SELECT *
FROM Hangar
WHERE NOT EXISTS
(SELECT *
FROM PilotSkills
WHERE (Pilots.pilot_name = PilotSkills.pilot_name)
AND (PilotSkills.plane_name = Hangar.plane_name)));
<强>飞行员强>
pilot_name
===========
'Celko'
'Higgins'
<强>机库强>
plane_name
=============
'B-1 Bomber'
'F-14 Fighter'
<强> PilotSkills 强>
pilot_name plane_name
=========================
'Celko' 'F-14 Fighter'
'Higgins' 'B-1 Bomber'
'Higgins' 'F-14 Fighter'
如果你想知道哪些飞行员可以飞机库中的所有飞机那么
Pilots.pilot_name
Hangar.plane_name
PilotSkills
pilot_name,plane_name
中是否有相应的行
醇>
如果步骤3为假,那么我们知道机库中至少有一架飞机无法飞行,我们可以停止处理Pilots
行并进入下一行。如果步骤3为真,那么我们必须返回步骤2并检查机库中的下一个平面。如果我们完成处理机库中的所有飞机并且每个飞机在PilotSkills
中都有相应的行,那么我们就知道这个飞行员可以飞行所有飞机。
或者换句话说我们知道没有一个平面(因为我们已经检查过它们),PilotSkills
表中没有匹配的行。