首页 文章

带有NOT EXISTS的嵌套SQL查询

提问于
浏览
0

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

关系模式:

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

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 回答

  • 1

    如果将它们分解为逻辑“块”,我会发现这些类型的查询更容易 .

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

    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的别名是由于我在“外部”语句中选择#Airports以及“内部”(子查询)语句 . 如果我不这样做,它会让两者混淆,不知道使用哪个引用 . 我做的最后一件事是我将两个Not Exists绑回主查询 . 这称为关联,这只是一种方法,可以确保当您从#Flights中选择时,您只需为您选择的机场(意大利机场)提供航班

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

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

相关问题