如何找到两个机场之间的最短距离/旅行时间?

时间:2010-08-09 22:30:26

标签: sql sql-server

问题是由我创造的,与我的同事讨论过,似乎没有人有任何想法。因此,想想,我可以在这里问专家。

我有下表   FlightInfo和字段是

 Start
 Destination
 Flight_Duration 

目标是找出两个城市之间最短的航班。挑战并非所有城市都有直飞航班。 (例如:PHL到PVA - >费城到上海)。你必须在底特律(DTW)或芝加哥(ORD)连接

您将如何编写SQL语句?

示例表格内容

PHL DTW 2.25

DTW PVG 15.15

PHL ORD 3.15

ORD PVG 16.20

2 个答案:

答案 0 :(得分:2)

蛮力:

declare @t table (
 [from] char(3), 
 [to] char(3),
 [time] float);

 insert into @t 
    ([from], [to], [time])
values  
 ('PHL', 'DTW', 2.25),
 ('DTW', 'PVG', 15.15),
 ('PHL', 'ORD', 3.15),
 ('ORD', 'PVG', 16.20);

 declare @src char(3) = 'PHL',
   @dst char(3) = 'PVG';

with cteAnchor as (
select case @src 
    when [from] then [to] 
    when [to] then [from]
    end as [layover], [time]
    , [time] as [total]
    , cast([from]+'-'+[to] as varchar(max)) as [path]
    , 1 as [flights]
from @t
where @src in ([from], [to]))
, cteRecursive as (
select [layover], [time], [total], [path], [flights]
from cteAnchor
union all
select case r.layover
    when [from] then [to]
    when [to] then [from] 
    end as [layover]
    , t.[time]
    , t.[time] + r.[total] as [total]
    , r.[path] + ' ' +t.[from]+'-'+t.[to] as [path]
    , r.[flights] + 1
from @t t
join cteRecursive r
    on  (t.[from] = r.[layover] and 0 = charindex(t.[to], r.[path]))
        or 
        (t.[to] = r.[layover] and 0 = charindex(t.[from], r.[path]))
)
select top(1) [flights], [total], [path] from cteRecursive  
where @dst = [layover]
order by [total] asc;

答案:

total   path
17.4    PHL-DTW DTW-PVG

编辑注释:我已经修改了CTE的实现,其中一个对周期具有弹性并且实际上也是正确的。

答案 1 :(得分:1)

我会假设您最多可以在三个航班上从任何一个机场到达任何一个机场。在极少数非常特殊的情况下,它可能不是真的,但这真的是一个问题吗?我不这么认为,但如果您觉得需要,可以考虑添加另一个联接。

Table flights:
origin      VARCHAR
destination VARCHAR
start       DATETIME
end         DATETIME

并查询:

SELECT *, f3.end - f1.end AS duration
FROM flights AS f1
INNER JOIN flights AS f2
ON f1.destination = f2.origin AND f1.end < f2.start
INNER JOIN flights AS f3
ON f2.destination = f3.origin AND f2.end < f3.start
WHERE f1.start BETWEEN some_reasonable_values_not_to_have_too_many_rows_in_join
  AND f2.start BETWEEN some_reasonable_values_not_to_have_too_many_rows_in_join
  AND f3.start BETWEEN some_reasonable_values_not_to_have_too_many_rows_in_join
  AND f1.origin = your_desired_origin
  AND f3.destination = your_desired_destination
ORDER BY duration ASC
LIMIT 1

这是三个航班的组合。两个航班和一个航班(较少的连接)的类似SQL。然后,结合这三个查询并获得最佳结果。

您可能希望在航班之间添加一些最小延迟。 Some_reasonable_values_not_to_have_too_many_rows_in_join - 搜索花费时间超过例如{1}}的航班组合是否有意义三天?