Mysql如何加入这些表

时间:2014-04-06 13:58:19

标签: mysql

我有以下表格和样本数据。

SCHEDULE TABLE
fightno   day_of_week  orgin    dest  depart_time   arrive_time     totalfare
AQ2131    WED          BLR      KTA   04:30         11:00           6000

FLIGHT_STOPS (if it have stops)
flightno  day_of_week  airport_code   arrival_time  departure_time  stopmilesfare
AQ2131    WED          BOM            02:17         05:40           3000 
AQ2131    WED          COH            03:17         06:40           3000 
AQ2131    WED          GOY            04:17         08:40           3000

航线将是BLR - > BOM - > COH - > GOY - > KTA

如何加入这些表,以便在用户输入任何这些表作为源和目标时,检索flightno。例如,如果用户输入BLR作为源,COH作为目的地或COH作为源,GOY作为目的地,我们可以找到航班号。

2 个答案:

答案 0 :(得分:1)

这是使用CTE和ROW_NUMBER的TSQL代表缺少的LegNo。我现在没有时间将其翻译成MySQL,但是LegNo已经存在,这将非常容易。

此外,ISNULL(x,y)不是MySQL,但是应该转换为CASE WHEN x IS NOT NULL,ELSE x END。

CREATE TABLE Schedule (FlightNo CHAR(6), Week_Day CHAR(3), Origin CHAR(3), Dest CHAR(3), Time_Depart Time, Time_Arrive Time)
CREATE TABLE Flight_Stop (FlightNo CHAR(6), Week_Day CHAR(3), Airport CHAR(3), Time_Arrive Time, Time_Depart Time)

INSERT INTO Schedule VALUES 
 ('AQ2131','WED','BLR','KTA','01:30','11:00')
,('AB1234','TUE','AAA','BBB','01:00','02:00')
INSERT INTO Flight_Stop VALUES 
 ('AQ2131','WED','BOM','02:17','05:40')
,('AQ2131','WED','COH','03:17','06:40')
,('AQ2131','WED','GOY','04:17','08:40')

WITH cte AS (
  SELECT *
        ,ROW_NUMBER() OVER (PARTITION BY FlightNo, Week_Day ORDER BY Time_Arrive) LegNo 
    FROM Flight_Stop
)
SELECT s.FlightNo
      ,s.Week_Day
      ,s.Origin
      ,ISNULL(f.Airport,s.Dest) Dest
      ,0 LegNo
  FROM Schedule s
       LEFT JOIN
       cte f ON s.FlightNo = f.FlightNo
            AND s.Week_Day = f.Week_Day
 WHERE ISNULL(f.LegNo,1) = 1
UNION 
SELECT s.FlightNo
      ,s.Week_Day
      ,s.Origin
      ,ISNULL(f.Airport,s.Dest) Dest
      ,f.LegNo
  FROM Schedule s
       LEFT JOIN
       cte f ON s.FlightNo = f.FlightNo
            AND s.Week_Day = f.Week_Day
 WHERE f.LegNo = (SELECT MAX(LegNo)
                    FROM cte a 
                   WHERE a.FlightNo = f.FlightNo
                     AND a.Week_Day = f.Week_Day)
UNION
SELECT a.FlightNo
      ,a.Week_Day
      ,a.Airport
      ,b.Airport
      ,a.LegNo
  FROM cte a
       INNER JOIN
       cte b ON a.FlightNo = b.FlightNo
            AND a.Week_Day = b.Week_Day
            AND a.LegNo + 1 = b.LegNo

答案 1 :(得分:1)

首先,让我们退一步。航班仅作为一个方向从A到D,或D到A,这是两个不同的航班号。您必须有正确的方向相关才能获得正确的飞行。对于笑容,一个想象中的国际

Flight #123 From Country A -> B -> C -> D.
Flight #987 From Country D -> C -> B -> A.

两次旅行都有国家'C'和'B'......但是如果我们的行程是从'C'开始并以'B'结束,那么你需要飞行#987,因为你需要在飞机上'C'并停在'B' - 那个方向。第123次飞行会失败,因为你会在'A'处'A'离开,然后到'C'站下来接听。我将使用'CCC'和'BBB'来符合3个char机场代码和查询。

第一次查询(将成为UNION ALL的一部分)获取在指定位置开始的所有航班...并且目的地或行程中的一条腿的目的地是所需“BBB”位置的目的地。通过在相同的航班和目的地机场代码上使用左/加入,如果它不是NULL,那么那条目的地就是一条腿。

SELECT 
      s1.flightNo
   from 
      schedule s1
         LEFT JOIN flight_stops fs1
            ON s1.flightNo = fs1.flightNo
            AND fs1.airport_code = 'BBB'
   where 
          s1.origin = 'CCC'
      AND (    s1.dest = 'BBB'
           OR fs1.flightNo IS NOT NULL )

下一个查询(UNION ALL)将获得从其他地方开始的任何航班,并将该航班的一条航线作为旅行的起始航班('CCC')。然后它将加入计划表,以查看该航班的目的地是否为“BBB”。如果不是这样,那么还会再次查看航班停靠表,但专门针对'BBB',其到达时间是在'CCC'起飞航班时间之后。

SELECT 
      fs1.flightNo
   from 
      flight_stops fs1
         LEFT JOIN schedule s2
             ON fs1.flightNo = s2.flightNo
            AND s2.dest = 'BBB'

         LEFT JOIN flight_stops fs2
             ON fs1.flightNo = fs2.flightNo
            AND fs1.arrival_time < fs2.arrival_time
            AND fs2.airport_code = 'BBB'
   where 
      fs1.airport_code = 'CCC'

因为我们得到的只是航班号,所以我们联合起来。由于航班不能同时开始和成为一条腿,他们永远不会拉同一航班。如果你想要实际的其余航班信息,你也可以把它包起来。

因此,航班的最终查询将是

(first select above)
UNION ALL
(second select above)

使用航班标题信息......

SELECT
      s.*
   from
      ( (first select above)
         UNION ALL
         (second select above) ) QualFlights
      JOIN Schedule s
         ON QualFlights.flightNo = s.flightNo

现在,所有这一切,如果你的flight_stops表包含原点和目的地位置,那将会更加容易。然后,整个查询可以简化为并在flight_stops上有索引...(airport_code,flightNo,arrival_time)

  SELECT 
          fs1.flightNo
       from 
          flight_stops fs1
             LEFT JOIN flight_stops fs2
                 ON fs1.flightNo = fs2.flightNo
                AND fs1.arrival_time < fs2.arrival_time
                AND fs2.airport_code = 'BBB'
       where 
          fs1.airport_code = 'CCC'

是的......通过在航班表的“支路”中设置始发地和目的地这一个查询是您基本上需要的。