🙏 感谢您的支持! 我们在七月份已经筹集了 $65 — 这足够我们工作到下个月。请帮助我们保持进度,进一步支持这个项目。 支持这个项目 →
SQL 代码已复制到剪贴板

分析 SQL 任务: 寻找有一次中转的航班

这个任务是使用 SQL 中最强大的工具之一来分析数据关系的一个优秀示例:将表连接到自身(自连接)。让我们逐步分解解决方案逻辑。

任务描述

我们需要找到从普尔科沃机场 (LED) 到布良斯克 (BZK) 的所有可能航班选项,这些航班包括恰好一次中转。

关键思想

一次中转的航线并不是一条,而是两条独立的航班通过一个中转机场连接在一起。

  • 段落 1: 从 LED 出发到某个中转机场 C。
  • 段落 2: 从同一个机场 C 出发到达 BZK。

我们的目标是找到所有这样的航班对,其中第一航班的到达机场与第二航班的出发机场匹配。

技术方法: 自连接

为了实现这个逻辑,我们将航班表视为两个不同的表。我们在脑海中为它创建两个别名,例如 first_leg(第一段)和 second_leg(第二段)。

步骤解决方案计划

  1. 定义航线的第一段。 我们使用别名 first_leg 来查找所有从我们的起点出发的航班。

    • 条件: first_leg.departure_airport = 'LED'
  2. 定义航线的第二段。 使用别名 second_leg,我们查找所有到达我们目的地的航班。

    • 条件: second_leg.arrival_airport = 'BZK'
  3. 找到连接点(关键 JOIN 条件)。 现在最重要的事情是:我们需要将这两组航班连接起来。我们在条件上将它们结合在一起,即第一段的到达机场必须与第二段的出发机场完全匹配。

    • 连接条件: first_leg.arrival_airport = second_leg.departure_airport
    • 这个共同的机场就是我们所需的中转机场 (connection_airport)。
  4. 检查中转时间: 我们还需要确保第二个航班在第一个航班到达 之后 起飞。这是通过以下条件确保的:

    • second_leg.scheduled_departure > first_leg.scheduled_arrival - 这个条件确保我们只考虑在航班之间有足够时间进行转机的连接。
  5. 形成结果。 在表连接后,我们在一行中拥有所有必要的信息。我们可以选择:

    • first_leg 中选择出发机场 (departure_airport)。
    • 中转机场(这是 first_leg.arrival_airport 或等效的 second_leg.departure_airport)。
    • second_leg 中选择目的地机场 (arrival_airport)。
  6. 排序。 最后,我们只需要按中转机场字段对结果列表进行排序,以满足任务条件。

因此,自连接使我们能够 "展开" 一张表,并将其中的行相互匹配,从而找到复杂的多阶段航线。

剧透:解决方案的 SQL 查询隐藏在下面。点击以显示。

        select 
            first_leg.flight_no flight1_no,
            first_leg.departure_airport,
            first_leg.arrival_airport connection_airport,
            first_leg.scheduled_arrival - first_leg.scheduled_departure flight1_time,
            second_leg.scheduled_departure - first_leg.scheduled_arrival connection_time,
            second_leg.flight_no flight2_no,
            second_leg.arrival_airport,
            second_leg.scheduled_arrival - second_leg.scheduled_departure flight2_time,
            (second_leg.scheduled_arrival - first_leg.scheduled_departure) total_trip_time
        from flights first_leg
        join flights second_leg on first_leg.arrival_airport=second_leg.departure_airport 
            and second_leg.arrival_airport = 'BZK'
            and second_leg.scheduled_departure > first_leg.scheduled_arrival
        where first_leg.departure_airport = 'LED'
            and first_leg.scheduled_departure between '2017-08-16' and '2017-08-17'
            and second_leg.scheduled_departure between '2017-08-16' and '2017-08-17'
        order by (second_leg.scheduled_arrival - first_leg.scheduled_departure)
        limit 1;