尝试使用SQL查询获取公共传输的直接,间接,交叉路由

时间:2015-11-10 13:49:53

标签: sql sql-server database

我正在尝试建立一个查询,从A到B获得一条路线。有时可能会有直接路线,有时我需要找到路口并获得交换路线。目标是让一个人从A到B旅行并给出不同的模式类型和路线。我将在稍后添加最短或最佳路线,但现在只是为了获得正确的路线。问题是当我试图获得相交路线时。不知何故,我觉得应该有一个更简单的方法来完成这项工作。我希望这不是太多的代码。

我认为应该运作的逻辑是

  1. 找到起始路线(Halts表),如果我们有一个获取RouteID和路线号,如果我们找不到起跑路线,试着去下一个最近的路线。

  2. 找到结束路线。如果我们有一个,检查起始路线是否在此路线内(这是直接路线),如果是,则获取RouteID和路线编号并插入临时表以显示最终路线。

    1. 如果第2点没有结束路线,请尝试从起点找到相交路线,并查找是否有相交的路线,如果是,则获取该路线ID和路线编号。从交叉路线尝试我们是否可以到达终点路线this is where I got lost as there can be more than one intersecting route
  3. 路线类型表

    此表有不同的路线类型,如城市巴士,长途巴士,本地火车,长途列车,国内航班,国际航班

        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]
    

    ModeTypes表

    此表格将包含不同的交通工具类型,如公共汽车,火车,航班

    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].[Halts](
        [HaltID] [int] IDENTITY(1,1) NOT NULL,
        [Halt] [nvarchar](100) NOT NULL
    ) 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 我发现这些链接很有趣,所以在这里添加

    This link is something similar to what I am trying to do

1 个答案:

答案 0 :(得分:2)

您需要使用旅行费用创建网络网格,以便使用Travel Salesman Promblemdjistra

short A*算法解决旅行问题

就我而言,我使用postgres lib PgRouting http://workshop.pgrouting.org/chapters/shortest_path.html#

在图表中

  • 红色均值地铁路线
  • 绿色高速公路路线
  • 绿点表示起点a
  • 蓝点平均终点
  • 黄点平均火车站。通常在道路连接中结束/开始,这样您就可以进行路线转换。

链接

  • 道路将有一些速度,如60-80 kmh
  • 道路行走速度也是3kmh
  • 训练60 kmh的恒定速度

这样您就可以使用TSP算法来优化成本。您使用每种速度计算成本以计算Time = Distance / Speed或仅计算distance。您也可以在使用像忽略总线路由之类的算法之前更改select中的网格。或使用实时交通改变道路速度

enter image description here