乘车线路查询

 
背景
有如下表示乘车线路和站点的数据,要求查询出指定站点之间的所有乘车线路:
USE tempdb
GO
 
-- 模拟数据
SET NOCOUNT ON
IF OBJECT_ID(N'tempdb..#tb') IS NOT NULL
    DROP TABLE #tb
CREATE TABLE #tb(
    id int IDENTITY
        PRIMARY KEY,
    lineID int,
    state nvarchar(10),
    orderid int
)
INSERT #tb(
     lineID, state, orderid)
SELECT 1, N' 广州东 ' , UNION ALL
SELECT 1, N' 体育中心 ' , UNION ALL
SELECT 1, N' 体育西 ' , UNION ALL
SELECT 1, N' 烈士陵园 ' , UNION ALL
SELECT 1, N' 公园前 ' , UNION ALL
SELECT 1, N' 西门口 ' , UNION ALL
SELECT 2, N' 火车站 ' , UNION ALL
SELECT 2, N' 纪念堂 ' , UNION ALL
SELECT 2, N' 公园前 ' , UNION ALL
SELECT 2, N' 中大 ' , UNION ALL
SELECT 2, N' 客村 ' , UNION ALL
SELECT 2, N' 琶洲 ' , UNION ALL
SELECT 2, N' 万胜围 ' , UNION ALL
SELECT 3, N' 广州东 ' , UNION ALL
SELECT 3, N' 体育西 ' , UNION ALL
SELECT 3, N' 珠江新城 ' , UNION ALL
SELECT 3, N' 客村 ' , UNION ALL
SELECT 3, N' 市桥 ' , UNION ALL
SELECT 4, N' 万胜围 ' , UNION ALL
SELECT 4, N' 金洲 ' , 2
 
CREATE INDEX IX_lineID
    ON #tb(
        lineID)
 
CREATE INDEX IX_state
    ON #tb(
        state)
 
CREATE INDEX IX_orderid
    ON #tb(
        orderid)
GO
 
处理方法:
之前也有发表过一些如何处理这个问题的方法,但效率不是太好。下面的这种方法加上了乘车方向的考虑:同一条线路上,只有两个乘车方向,而且一旦方向了,就不会再反向乘车(因为是从这个方向来,再坐回去是不合理的);如果某个站点可以换到另一条线路,则换乘后的另一条线路也是两个方向乘车。通过乘车方向的控制,减少了算法要搜索的路径。
-- 乘车路线查询
DECLARE
    @state_start nvarchar(10),
    @state_stop nvarchar(10)
SELECT
    @state_start = N' 广州东 ' ,
    @state_stop = N' 中大 '
 
-- 查询
IF OBJECT_ID(N'tempdb..#re') IS NOT NULL
    DROP TABLE #re
CREATE TABLE #re(
    ID int IDENTITY
       PRIMARY KEY,
    path nvarchar(max),
    state_count int,
    line_count int,
    start_lineID int,
    start_state nvarchar(10),
    current_lineID int,
    current_state nvarchar(10),
    next_orderid int,
    flag int,
    lineIDs varchar(max),
    level int
)
 
CREATE INDEX IX_current_lineID
    ON #re(
       current_lineID )
 
CREATE INDEX IX_current_state
    ON #re(
       current_state )
 
CREATE INDEX IX_next_orderid
    ON #re(
       next_orderid )
 
CREATE INDEX IX_current_level
    ON #re(
       level )
 
DECLARE
    @level int,
    @rows int
SET
    @level = 0
 
-- 开始
INSERT #re(
    path,
    state_count, line_count,
    start_lineID, start_state,
    current_lineID, current_state,
    next_orderid, flag, lineIDs, level)   
SELECT
    path = CONVERT(nvarchar(max),
           RTRIM(A.lineID) + N'{'
              + RTRIM(A.orderid) + N'.' + A.state
       ),
    state_count = 0,
    line_count = 0,
    start_lineID = A.lineID,
    start_state = A.state,
    current_lineID = A.lineID,
    current_state = A.state,
    next_orderid = A.orderid,
    flag = CASE
           WHEN A.state = @state_stop THEN 0
           ELSE NULL END,
    lineIDs = ',' + RTRIM(A.lineID) + ',',
    level = -(@level + 1)
FROM #tb A
WHERE state = @state_start
SET @rows = @@ROWCOUNT
WHILE @rows > 0
BEGIN
    SELECT
       @level = @level + 1
    INSERT #re(
       path,
       state_count, line_count,
       start_lineID, start_state,
       current_lineID, current_state,
       next_orderid, flag, lineIDs, level)   
    -- 同一 LineID
    SELECT
       path = CONVERT(nvarchar(max),
              A.path
                  + N'->'
                  + RTRIM(B.orderid) + N'.' + B.state
           ),
       state_count = A.state_count + 1,
       A.line_count,
       A.start_lineID, A.start_state,
       current_lineID = B.lineID,
       current_state = B.state,
       next_orderid = B.orderid + A.flag,
       flag = CASE
              WHEN B.state = @state_stop THEN 0
              ELSE A.flag END,
       A.lineIDs,
       level = @level
    FROM #re A, #tb B
    WHERE A.flag <> 0
       AND A.level = @level - 1
       AND A.current_lineID = B.lineID
       AND A.next_orderid = B.orderid
   
    UNION ALL
    -- 不同 LineID
    SELECT
       path = CONVERT(nvarchar(max),
              A.path + N')->'
                  + RTRIM(B.lineID) + N'{'
                  + RTRIM(B.orderid) + N'.' + B.state
           ),
       state_count = A.state_count + 1,
       line_count = A.line_count + 1,
       A.start_lineID, A.start_state,
       current_lineID = B.lineID,
       current_state = B.state,
       next_orderid = B.orderid,
       flag = CASE
              WHEN B.state = @state_stop THEN 0
              ELSE NULL END,
       A.lineIDs + RTRIM(B.lineID) + ',',
       level = - @level
    FROM #re A, #tb B
    WHERE A.flag <> 0
       AND state_count = @level - 1
       AND A.current_lineID <> B.lineID
       AND A.current_state = B.state
       AND NOT EXISTS(
              SELECT * FROM #re
              WHERE CHARINDEX(',' + RTRIM(B.lineID) + ',', A.lineIDs) > 0)
    SET @rows = @@ROWCOUNT
 
    INSERT #re(
       path,
       state_count, line_count,
       start_lineID, start_state,
       current_lineID, current_state,
       next_orderid, flag, lineIDs, level)   
    -- 不同 LineID 的第站正向
    SELECT
       path = CONVERT(nvarchar(max),
              A.path
                  + N'->'
                  + RTRIM(B.orderid) + N'.' + B.state
           ),
       state_count = A.state_count + 1,
       A.line_count,
       A.start_lineID, A.start_state,
       current_lineID = B.lineID,
       current_state = B.state,
       next_orderid = B.orderid + 1,
       flag = CASE
              WHEN B.state = @state_stop THEN 0
              ELSE 1 END,
       A.lineIDs,
       level = @level
    FROM #re A, #tb B
    WHERE A.flag IS NULL
       AND A.level = - @level
       AND A.current_lineID = B.lineID
       AND A.next_orderid + 1 = B.orderid
    UNION ALL
    -- 不同 LineID 的第站反向
    SELECT
       path = CONVERT(nvarchar(max),
              A.path
                  + N'->'
                  + RTRIM(B.orderid) + N'.' + B.state
           ),
       state_count = A.state_count + 1,
       A.line_count,
       A.start_lineID, A.start_state,
       current_lineID = B.lineID,
       current_state = B.state,
       next_orderid = B.orderid - 1,
       flag = CASE
              WHEN B.state = @state_stop THEN 0
              ELSE - 1 END,
       A.lineIDs,
       level = @level
    FROM #re A, #tb B
    WHERE A.flag IS NULL
       AND A.level = - @level
       AND A.current_lineID = B.lineID
       AND A.next_orderid - 1 = B.orderid
 
    SET @rows = @rows + @@ROWCOUNT
END
 
SELECT
-- *,
    path = path + N'}',
    line_count,
    state_count
FROM #re
WHERE flag = 0
 
 
随着经济的飞速发展,汽车越来越多,城市的道路建设远赶不上城市化进程的加快,交通拥堵已成为制约城市发展的重要问题之一。城市公共交通覆盖面广、经济快捷。为了缓解交通压力,必须大力发展公共交通,提高公交服务水平,鼓励和吸引市民选择乘坐公交出行,从而改善交通状况。为此我们设计开发了基于Web的公交查询系统,为乘客出行提供详细全面的信息,进一步提高公交的服务水平。 本文从乘客的角度出发,研究了乘客的出行行为,对公交查询系统进行了需求分析;从系统开发环境、系统目标、设计流程、功能设计、模块设计和数据库设计六个方面进行系统的总体设计;通过抽象公交网络中的站点和线路,建立了公交网络数学模型,讨论了公交网络的最优路径算法,并在此基础上详细介绍了在三种不同目标情况下适合公交查询的最优路径算法;在需求分析、总体设计和基于网络路径最优的公交查询算法探讨基础上,对查询系统进行了详细设计,并成功将三种网络路径算法应用于系统的换乘查询中,系统还实现了线网维护、线路查询、站点查询和标志性地点查询的功能,最后利用武汉市25条线路和400个站点的实验数据,对系统的功能进行了测试,并对公交网络路径的算法时间和查询结果进行了分析。实验证明该系统界面友好、功能完善。
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值