我有以下表格和样本数据。
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作为目的地,我们可以找到航班号。
答案 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'
是的......通过在航班表的“支路”中设置始发地和目的地这一个查询是您基本上需要的。