NOT EXISTS 的嵌套 SQL 查询

Nested SQL query with NOT EXISTS

一段时间以来,我一直在努力弄清楚这个问题,但一直无法解决。

关系模式:

Airport(name, country) -> name为主键

Flight(dep_airport, arr_airport) -> 两个属性都是引用 Airport(name)

的外键

问题是:

find Italian airports that do not have any international flights. The SQL query has to be nested and use the NOT EXISTS operator.

这是我目前所拥有的,但它不起作用:

SELECT A.name
FROM airport AS A
WHERE NOT EXISTS (
    SELECT dep_airport.name AS dep_name, 
        dep_airport.country AS dep_country,
        arr_airport.name AS arr_name, 
        arr_airport.country AS arr_country
    FROM flight
    INNER JOIN airport dep_airport ON dep_airport.name = flight.dep_airport
    INNER JOIN airport arr_airport ON arr_airport.name = flight.arr_airport
    WHERE dep_airport.country <> arr_airport.country)

另外,如何将其写成关系代数查询?

谢谢:)

这可能有用...如果不行,请忽略。

CREATE TABLE Airports (
  Name VARCHAR(50),
  Country VARCHAR(50)
);

INSERT INTO Airports
VALUES  ('ABC', 'Italy'), ('DEF', 'Germany'), 
        ('GHI', 'Italy'), ('JKL', 'France'), 
        ('MNO', 'England'), ('PQR', 'Italy');

CREATE TABLE Flights (
  Departing VARCHAR(50),
  Arriving VARCHAR(50)
);

INSERT INTO Flights
VALUES  ('ABC', 'PQR'), ('ABC', 'GHI'), 
        ('GHI', 'DEF'), ('JKL', 'GHI'), 
        ('MNO', 'PQR'), ('PQR', 'GHI'), ('ABC', 'PQR');


SELECT DISTINCT Departures.Name
FROM (Flights INNER JOIN Airports Departures ON Departures.Name = Flights.Departing) 
    INNER JOIN Airports Arrivals ON Arrivals.Name = Flights.Arriving
WHERE Departures.Country = Arrivals.Country
      AND EXISTS (SELECT * 
                  FROM Airports
                  WHERE Airports.Country = 'Italy')

如果将这些类型的查询分解为符合逻辑的 "chunks"。

,我发现它们会更容易

您首先需要找到所有意大利机场

Select * from #Airports Where Country = 'Italy'

您需要做的第二件事是找到从到达机场不是意大利的每个机场起飞的所有航班。

Select * 
from #Flights 
Inner Join #Airports on #Flights.Arriving = #Airports.Name
And #Airports.Country <> 'Italy'

现在您需要做完全相反的事情,找到所有从出发机场不是意大利的机场到达的所有航班。

Select * 
from #Flights 
Inner Join #Airports on #Flights.Departing= #Airports.Name
And #Airports.Country <> 'Italy'

此时您已拥有满足要求所需的 3 条语句,但您必须将它们全部放在一条语句中。您将从第一个语句开始,因为这就是您想要 return 给用户的内容(机场列表)。然后,您将使用每个不存在的子查询将接下来的两个语句添加为子查询。

Select  *
From    #Airports A
Where   Country = 'Italy'
And Not Exists  (
                    Select  1
                    From    #Flights F
                    Inner Join #Airports ASub on F.Arriving = ASub.Name
                    Where   A.Name = F.Departing
                    And     ASub.Country <> 'Italy'
                )
AND Not Exists  (
                    Select  1
                    From    #Flights F
                    Inner Join #Airports ASub on F.Departing = ASub.Name
                    Where   A.Name = F.Arriving
                    And     ASub.Country <> 'Italy'
                )

您应该注意到两个 Not Exists 语句的一些细微调整。主要是,我为#Airports table 添加了别名,并在 where 子句中添加了一个条件。 #Airports 的别名是因为我在 "outer" 语句和 "inner"(子查询)语句中从 #Airports selecting。如果我不那样做,就会把两者混淆,不知道使用哪个参考。我做的最后一件事是将两个 Not Exists 绑定回主查询。这称为关联,它只是一种确保当您从#Flights select 时,您只为您正在 selecting 的机场(意大利机场)[=14] 提取航班的方法=]

Exists 和 Not Exists 语句的主要好处之一是它通常允许您从语句中删除 distinct 关键字。当 return 处理大量数据时,Distinct 可能会导致极端的性能下降。它还可以使查询更易于阅读。