带有NOT EXISTS的嵌套SQL查询

时间:2015-04-24 02:54:01

标签: sql postgresql rdbms

我一直试图找出这个问题一段时间,但无法让它发挥作用。

关系架构:

机场(名称,国家) - > name是主键

Flight(dep_airport,arr_airport) - >两个属性都是引用机场(名称)的外键

问题是:

  

查找没有任何国际航班的意大利机场。该   SQL查询必须嵌套并使用NOT EXISTS运算符。

这是我到目前为止所做的,但它不起作用:

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)

而且,如何将其写为关系代数查询?

谢谢:)

2 个答案:

答案 0 :(得分:1)

如果您将这些类型的查询分解为逻辑&#34;块&#34;我会发现这些类型的查询更容易。

您需要的第一件事就是找到所有意大利机场

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个语句,但必须将它们放在一个语句中。您将从第一个声明开始,因为那是您想要返回给用户的内容(机场列表)。然后,您将使用不存在的子查询添加接下来的两个语句。

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表别名,我在where子句中添加了一个条件。 #Airports的别名是因为我在&#34;外部&#34;中选择了#Airports。声明以及&#34;内部&#34; (子查询)声明。如果我没有这样做,它会让两者混淆,不知道使用哪个引用。我做的最后一件事是我把两个Not Exists绑回主查询。这称为关联,它只是一种方法,可以确保当您从#Flights中选择时,您只是为您选择的机场(意大利机场)拉入航班

Exists和Not Exists语句的主要好处之一是它通常允许您从语句中删除distinct关键字。返回大量数据时,不同可能会导致极端的性能命中。它还可以使查询更容易阅读。

答案 1 :(得分:-1)

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

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')