尝试使用sql查询获取公共交通的直接、间接、交叉路线
我正在尝试构建一个查询,以获取从a到B的路线。有时可能存在直接路线,有时我需要找到交叉点并获取交换路线。目标是让一个人从a旅行到B,并给出不同的模式类型和路线。我会添加最短或最好的路线后,但现在只是为了得到正确的路线。问题是当我试图获得相交路线时。不知何故,我觉得应该有一个更简单的方法来完成这件事。我希望这不是太多的代码 我认为应该起作用的逻辑是尝试使用sql查询获取公共交通的直接、间接、交叉路线,sql,sql-server,database,Sql,Sql Server,Database,我正在尝试构建一个查询,以获取从a到B的路线。有时可能存在直接路线,有时我需要找到交叉点并获取交换路线。目标是让一个人从a旅行到B,并给出不同的模式类型和路线。我会添加最短或最好的路线后,但现在只是为了得到正确的路线。问题是当我试图获得相交路线时。不知何故,我觉得应该有一个更简单的方法来完成这件事。我希望这不是太多的代码 我认为应该起作用的逻辑是 查找起始路线(Halts表),如果有,请获取路线ID和路线编号,如果找不到起始路线,请尝试获取下一条最近的路线 找到终点路线。如果有,请检查起始路线是
这是我迷路的地方,因为可能有多条相交路线
CREATE TABLE [dbo].[RouteHalts](
[RouteHaltID] [int] IDENTITY(1,1) NOT NULL,
[RouteID] [int] NOT NULL,
[FirstLastHalt] [char](1) NULL,
[HaltNo] [smallint] NULL,
[HaltID] [int] NOT NULL,
CONSTRAINT [PK_RouteHalts] PRIMARY KEY CLUSTERED
(
[RouteHaltID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
此表包含不同的路线类型,如城市巴士、长途巴士、本地火车、长途火车、国内航班、国际航班
CREATE TABLE [dbo].[RouteTypes](
[RouteTypeID] [int] IDENTITY(1,1) NOT NULL,
[ModeTypeID] [int] NOT NULL,
[RouteType] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_RouteTypes] PRIMARY KEY CLUSTERED
(
[RouteTypeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
模式类型表
CREATE TABLE [dbo].[RouteHalts](
[RouteHaltID] [int] IDENTITY(1,1) NOT NULL,
[RouteID] [int] NOT NULL,
[FirstLastHalt] [char](1) NULL,
[HaltNo] [smallint] NULL,
[HaltID] [int] NOT NULL,
CONSTRAINT [PK_RouteHalts] PRIMARY KEY CLUSTERED
(
[RouteHaltID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
此表将容纳不同的运输类型,如公共汽车、火车、航班
CREATE TABLE [dbo].[ModeTypes](
[ModeTypeID] [int] IDENTITY(1,1) NOT NULL,
[ModeType] [nvarchar](50) NOT NULL,
[IsEnabled] [bit] NOT NULL,
CONSTRAINT [PK_ModeTypes] PRIMARY KEY CLUSTERED
(
[ModeTypeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
暂停表
CREATE TABLE [dbo].[RouteHalts](
[RouteHaltID] [int] IDENTITY(1,1) NOT NULL,
[RouteID] [int] NOT NULL,
[FirstLastHalt] [char](1) NULL,
[HaltNo] [smallint] NULL,
[HaltID] [int] NOT NULL,
CONSTRAINT [PK_RouteHalts] PRIMARY KEY CLUSTERED
(
[RouteHaltID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
此表将容纳所有暂停,是暂停的主表
CREATE TABLE [dbo].[Halts](
[HaltID] [int] IDENTITY(1,1) NOT NULL,
[Halt] [nvarchar](100) NOT NULL
) ON [PRIMARY]
路由表
CREATE TABLE [dbo].[RouteHalts](
[RouteHaltID] [int] IDENTITY(1,1) NOT NULL,
[RouteID] [int] NOT NULL,
[FirstLastHalt] [char](1) NULL,
[HaltNo] [smallint] NULL,
[HaltID] [int] NOT NULL,
CONSTRAINT [PK_RouteHalts] PRIMARY KEY CLUSTERED
(
[RouteHaltID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
此表将包含一些路线编号。因为我不太清楚需要在这里添加什么,所以我现在还没有使用的大多数字段
CREATE TABLE [dbo].[Routes](
[RouteID] [int] IDENTITY(1,1) NOT NULL,
[RouteTypeID] [int] NOT NULL,
[RouteNo] [nvarchar](30) NOT NULL,
[Duration] [nvarchar](30) NULL,
[Distance] [nvarchar](30) NULL,
[OldRouteNo] [nvarchar](30) NULL,
[DaysAvailable] [char](15) NULL,
[IsEnabled] [bit] NOT NULL,
[BeginAt] [time](7) NULL,
[EndAt] [time](7) NULL,
CONSTRAINT [PK_Routes] PRIMARY KEY CLUSTERED
(
[RouteID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
路由暂停表
CREATE TABLE [dbo].[RouteHalts](
[RouteHaltID] [int] IDENTITY(1,1) NOT NULL,
[RouteID] [int] NOT NULL,
[FirstLastHalt] [char](1) NULL,
[HaltNo] [smallint] NULL,
[HaltID] [int] NOT NULL,
CONSTRAINT [PK_RouteHalts] PRIMARY KEY CLUSTERED
(
[RouteHaltID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
我使用的是一个存储过程,这就是我到目前为止得到的。当我得到检查路线时,结果有些不正确
DECLARE @StartingRouteID int;
DECLARE @EndingRouteID int;
DECLARE @CrossRouteHalt nvarchar(100);
CREATE TABLE #TmpStartingRoute
(
ID INT IDENTITY(1,1) NOT NULL,
RouteID int null,
RouteNo nvarchar(60) null,
RouteType nvarchar(100) null,
Duration nvarchar(60) null,
Distance nvarchar(60) null,
DaysAvailable nvarchar(60) null,
Halt nvarchar(100) null,
ModeType nvarchar(100) null
)
CREATE TABLE #TmpStartingHalts
(
ID INT IDENTITY(1,1) NOT NULL,
RouteID int null,
RouteNo nvarchar(60) null,
RouteType nvarchar(100) null,
Duration nvarchar(60) null,
Distance nvarchar(60) null,
DaysAvailable nvarchar(60) null,
Halt nvarchar(100) null,
ModeType nvarchar(100) null
)
CREATE TABLE #TmpEndingRoute
(
ID INT IDENTITY(1,1) NOT NULL,
RouteID int null,
RouteNo nvarchar(60) null,
RouteType nvarchar(100) null,
Duration nvarchar(60) null,
Distance nvarchar(60) null,
DaysAvailable nvarchar(60) null,
Halt nvarchar(100) null,
ModeType nvarchar(100) null
)
CREATE TABLE #TmpEndingHalts
(
ID INT IDENTITY(1,1) NOT NULL,
RouteID int null,
RouteNo nvarchar(60) null,
RouteType nvarchar(100) null,
Duration nvarchar(60) null,
Distance nvarchar(60) null,
DaysAvailable nvarchar(60) null,
Halt nvarchar(100) null,
ModeType nvarchar(100) null
)
CREATE TABLE #TmpRts
(
ID INT IDENTITY(1,1) NOT NULL,
RouteID int null,
Halt nvarchar(100) null,
RouteNo nvarchar(60) null,
RouteType nvarchar(100) null,
ModeType nvarchar(100) null
)
CREATE TABLE #TmpIntersection
(
ID INT IDENTITY(1,1) NOT NULL,
RouteID int null,
Halt nvarchar(100) null,
RouteNo nvarchar(60) null,
RouteType nvarchar(100) null,
ModeType nvarchar(100) null
)
CREATE TABLE #FinalRoute
(
ID INT IDENTITY(1,1) NOT NULL,
RouteID int null,
RouteNo nvarchar(60) null,
Halt nvarchar(100) null,
RouteType nvarchar(100) null,
ModeType nvarchar(100) null
)
-- Check if Starting point exits
IF EXISTS(SELECT 1 FROM RouteHalts where Halt like'%'+ @StartingPoint +'%')
BEGIN
SELECT
@StartingRouteID=R.RouteID
from
ModeTypes M
inner join
RouteTypes RT on M.ModeTypeID=RT.ModeTypeID
inner join
Routes R on RT.RouteTypeID=R.RouteTypeID
inner join
RouteHalts RH on R.RouteID=RH.RouteID
where
RH.Halt like'%'+ @StartingPoint +'%'
insert into #TmpStartingRoute(RouteID,RouteNo,RouteType,Duration,Distance,DaysAvailable,Halt,ModeType)
SELECT
R.RouteID, R.RouteNo,RT.RouteType,R.Duration,R.Distance,R.DaysAvailable, RH.Halt,M.ModeType
from
ModeTypes M
inner join
RouteTypes RT on M.ModeTypeID=RT.ModeTypeID
inner join
Routes R on RT.RouteTypeID=R.RouteTypeID
inner join
RouteHalts RH on R.RouteID=RH.RouteID
where
RH.Halt like'%'+ @StartingPoint +'%'
order by
R.RouteNo,RH.HaltNo
-- Insert halts of starting routes
insert into #TmpStartingHalts(RouteID,RouteNo,RouteType,Duration,Distance,DaysAvailable,Halt,ModeType)
SELECT
R.RouteID, R.RouteNo,RT.RouteType,R.Duration,R.Distance,R.DaysAvailable, RH.Halt,M.ModeType
from
ModeTypes M
inner join
RouteTypes RT on M.ModeTypeID=RT.ModeTypeID
inner join
Routes R on RT.RouteTypeID=R.RouteTypeID
inner join
RouteHalts RH on R.RouteID=RH.RouteID
where
RH.RouteID=@StartingRouteID and RH.Halt not like'%'+ @StartingPoint +'%'
order by
R.RouteNo,RH.HaltNo
END
ELSE
-- Find the closest locaton of the starting point
BEGIN
RAISERROR('No Routes Available', 16, 2)
RETURN
END
-- Check if Ending point exits within the start route to get the direct route
IF EXISTS(SELECT 1 FROM RouteHalts R INNER JOIN #TmpStartingRoute SR on R.RouteID=SR.RouteID
where R.Halt like'%'+ @EndingPoint +'%')
BEGIN
print 'In End route exists within starting route'
SELECT
@EndingRouteID= R.RouteID
from
ModeTypes M
inner join
RouteTypes RT on M.ModeTypeID=RT.ModeTypeID
inner join
Routes R on RT.RouteTypeID=R.RouteTypeID
inner join
RouteHalts RH on R.RouteID=RH.RouteID
INNER JOIN
#TmpStartingRoute SR on R.RouteID=SR.RouteID
where
RH.Halt like'%'+ @EndingPoint +'%'
insert into #TmpEndingRoute(RouteID,RouteNo,RouteType,Duration,Distance,DaysAvailable,Halt,ModeType)
SELECT
R.RouteID,R.RouteNo, RT.RouteType,R.Duration,R.Distance,R.DaysAvailable, RH.Halt,M.ModeType
from
ModeTypes M
inner join
RouteTypes RT on M.ModeTypeID=RT.ModeTypeID
inner join
Routes R on RT.RouteTypeID=R.RouteTypeID
inner join
RouteHalts RH on R.RouteID=RH.RouteID
INNER JOIN
#TmpStartingRoute SR on R.RouteID=SR.RouteID
where
RH.Halt like'%'+ @EndingPoint +'%'
order by
R.RouteNo,RH.HaltNo
-- Insert all halts of ending route
insert into #TmpEndingHalts(RouteID,RouteNo,RouteType,Duration,Distance,DaysAvailable,Halt,ModeType)
SELECT
R.RouteID,R.RouteNo, RT.RouteType,R.Duration,R.Distance,R.DaysAvailable, RH.Halt,M.ModeType
from
ModeTypes M
inner join
RouteTypes RT on M.ModeTypeID=RT.ModeTypeID
inner join
Routes R on RT.RouteTypeID=R.RouteTypeID
inner join
RouteHalts RH on R.RouteID=RH.RouteID
where
RH.RouteID=@EndingRouteID and RH.Halt not like'%'+ @EndingPoint +'%'
order by
R.RouteNo,RH.HaltNo
delete from #TmpStartingHalts where RouteID not in (select RouteID from #TmpEndingRoute)
delete from #TmpStartingRoute where RouteID not in (select RouteID from #TmpEndingRoute)
select * from #TmpEndingRoute
END
ELSE
-- Find the closest locaton of the starting point
BEGIN
print 'In End route does NOT exists within starting route'
SELECT
@EndingRouteID= R.RouteID
from
ModeTypes M
inner join
RouteTypes RT on M.ModeTypeID=RT.ModeTypeID
inner join
Routes R on RT.RouteTypeID=R.RouteTypeID
inner join
RouteHalts RH on R.RouteID=RH.RouteID
where
RH.Halt like'%'+ @EndingPoint +'%'
insert into #TmpEndingRoute(RouteID,RouteNo,RouteType,Duration,Distance,DaysAvailable,Halt,ModeType)
SELECT
R.RouteID,R.RouteNo, RT.RouteType,R.Duration,R.Distance,R.DaysAvailable, RH.Halt,M.ModeType
from
ModeTypes M
inner join
RouteTypes RT on M.ModeTypeID=RT.ModeTypeID
inner join
Routes R on RT.RouteTypeID=R.RouteTypeID
inner join
RouteHalts RH on R.RouteID=RH.RouteID
where
RH.Halt like'%'+ @EndingPoint +'%'
order by
R.RouteNo,RH.HaltNo
-- Insert all halts of ending route
insert into #TmpEndingHalts(RouteID,RouteNo,RouteType,Duration,Distance,DaysAvailable,Halt,ModeType)
SELECT
R.RouteID,R.RouteNo, RT.RouteType,R.Duration,R.Distance,R.DaysAvailable, RH.Halt,M.ModeType
from
ModeTypes M
inner join
RouteTypes RT on M.ModeTypeID=RT.ModeTypeID
inner join
Routes R on RT.RouteTypeID=R.RouteTypeID
inner join
RouteHalts RH on R.RouteID=RH.RouteID
where
RH.RouteID=@EndingRouteID and RH.Halt not like'%'+ @EndingPoint +'%'
order by
R.RouteNo,RH.HaltNo
END
-- Get the intersection Routes
insert into #TmpRts(RouteID,Halt,RouteNo,RouteType,ModeType)
select RH.RouteID,RH.halt,TER.RouteNo,TER.RouteType,TER.ModeType
from
RouteHalts RH
INNER JOIN
#TmpEndingRoute TER on RH.RouteID=TER.RouteID
-- Get the intersection Halt
IF EXISTS( select 1 from RouteHalts RH INNER JOIN #TmpRts TER on TER.Halt=RH.Halt
where RH.RouteID in (select RouteID from #TmpStartingRoute))
begin
print 'in exists'
select
@CrossRouteHalt= TER.Halt
from
RouteHalts RH
INNER JOIN
#TmpRts TER on TER.Halt=RH.Halt
where RH.RouteID in (select RouteID from #TmpStartingRoute)
-- Insert into #TmpIntersection
insert into #TmpIntersection(RouteID,Halt,RouteNo,RouteType,ModeType)
select RH.RouteID,RH.Halt,RouteNo,RouteType,ModeType
from
RouteHalts RH
INNER JOIN
#TmpRts TER on TER.Halt=RH.Halt
where RH.RouteID in (select RouteID from #TmpStartingRoute)
end
-- If no intersection halt exsits then try to get the matching routes from the starting point halts
IF not EXISTS( select 1 from RouteHalts RH INNER JOIN #TmpRts TER on TER.Halt=RH.Halt
where RH.RouteID in (select RouteID from #TmpStartingRoute))
begin
print 'in not exists'
insert into #TmpRts(RouteID,Halt,RouteNo)
select distinct RH.RouteID,RH.halt,TSR.RouteNo
from
RouteHalts RH
INNER JOIN
#TmpStartingHalts TSR on RH.Halt=TSR.Halt
-- Update the Route type to show the current route type of the connecting routes
update TER
set TER.RouteType = RT.RouteType, TER.ModeType=MT.ModeType
from #TmpRts TER
INNER JOIN Routes R on TER.RouteID=R.RouteID
inner join
RouteTypes RT on R.RouteTypeID=RT.RouteTypeID
inner join
ModeTypes MT on RT.ModeTypeID=MT.ModeTypeID
select
@CrossRouteHalt= TSR.Halt
from
RouteHalts RH
INNER JOIN
#TmpRts TSR on TSR.Halt=RH.Halt
where RH.RouteID in (select RouteID from #TmpStartingHalts)
-- Insert into #TmpIntersection
insert into #TmpIntersection(RouteID,Halt,RouteNo,RouteType,ModeType)
select RH.RouteID,RH.Halt,RouteNo,RouteType,ModeType
from
RouteHalts RH
INNER JOIN
#TmpRts TSR on TSR.Halt=RH.Halt
where RH.RouteID in (select RouteID from #TmpStartingHalts)
end
/*
Insert all data in to #FinalRoute
*/
-- Insert the Starting Route record
insert into #FinalRoute(RouteID,Halt,RouteNo,RouteType,ModeType)
select RouteID,Halt,RouteNo,RouteType,ModeType from #TmpStartingRoute
-- Insert the Intersection Halt
insert into #FinalRoute(Halt)
select @CrossRouteHalt
-- Get the new Starting point
delete from #TmpRts where routeid in (select routeid from #TmpStartingRoute)
select RH.RouteID,RH.halt,R.RouteNo,TER.RouteType,TER.ModeType
into #TmpNewStartingPoint
from
RouteHalts RH
INNER JOIN
#TmpRts TER on RH.RouteID=TER.RouteID and TER.RouteID not in (select routeid from #TmpEndingRoute)
inner join Routes R on TER.RouteID=R.RouteID and TER.RouteID not in (select routeid from #TmpEndingRoute)
/*
Insert all data in to #FinalRoute
*/
-- Check if #TmpNewStartingPoint is empty then add the insersection route from #TmpRts else add the data from #TmpNewStartingPoint
IF NOT EXISTS(select 1 from #TmpNewStartingPoint)
BEGIN
print 'in no new starting point'
insert into #FinalRoute(RouteID,Halt,RouteNo,RouteType,ModeType)
select RouteID, Halt,RouteNo,RouteType,ModeType from #TmpRts where Halt=@CrossRouteHalt
END
IF EXISTS(select 1 from #TmpNewStartingPoint)
BEGIN
print 'in new starting point'
insert into #FinalRoute(RouteID,Halt,RouteNo,RouteType,ModeType)
select RouteID,Halt,RouteNo,RouteType,ModeType from #TmpNewStartingPoint where halt in (select halt from #TmpEndingHalts)
END
-- Insert the Ending Route record
insert into #FinalRoute(RouteID,Halt,RouteNo,RouteType,ModeType)
select RouteID,Halt,RouteNo,RouteType,ModeType from #TmpEndingRoute
select * from #FinalRoute
编辑1
我发现这些链接很有趣,所以在这里添加它
您需要创建一个包含旅行费用的网络网格,以便使用
旅行推销员问题算法解决旅行问题,如djistra
或short a*
在我的例子中,我使用postgres libPgRouting
在图表中
- 红色平均线地铁线路
- 绿色平均公路路线
- 绿点表示起点a
- 蓝点平均终点
- 黄点表示火车站。通常在道路连接中结束/开始,以便进行路线转换
链接
- 道路将有一些速度,如60-80公里小时
- 道路的行走速度也为3km/h
- 列车以60公里小时的恒定速度行驶
这样,您就可以使用TSP算法来优化成本。使用每个速度计算时间=距离/速度
或仅计算距离
,您可以指定一个成本。此外,您还可以在使用“忽略公交线路”等算法之前,在选择中更改网格。或者使用实时交通来改变道路速度
这是一个巨大的问题,我们只能在这里的答案中触及问题的表面;因此,我投了“过于广泛”的一票。@AakashM我仍在努力寻找是否有一种更简单的方法来看待这一点,但现在令人困惑。但我将尝试并在此添加更新我接受这个答案,因为我得到了如何继续的线索:)