如果将它们分解为逻辑“块”,我会发现这些类型的查询更容易 .
您需要的第一件事是找到所有意大利机场
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关键字 . 返回大量数据时,不同可能导致极端性能命中 . 它还可以使查询更容易阅读 .