公交车路线查询系统后台数据库设计说明.docx
- 文档编号:11147939
- 上传时间:2023-02-25
- 格式:DOCX
- 页数:50
- 大小:320.43KB
公交车路线查询系统后台数据库设计说明.docx
《公交车路线查询系统后台数据库设计说明.docx》由会员分享,可在线阅读,更多相关《公交车路线查询系统后台数据库设计说明.docx(50页珍藏版)》请在冰豆网上搜索。
公交车路线查询系统后台数据库设计说明
公交车路线查询系统后台数据库设计--查询算法
1.公交车路线信息在数据库中的存储方式
显然,如果在数据库中简单的使用表bus_route(路线名,路线经过的站点,费用)来保存公交车路线的线路信息,则很难使用查询语句实现乘车线路查询,因此,应该对线路的信息进行处理后再保存到数据库中,笔者使用的方法是用站点-路线关系表stop_route(站点,路线名,站点在路线中的位置)来存储公交车路线,例如,如果有以下3条路线
R1:
S1->S2->S3->S4->S5
R2:
S6->S7->S2->S8
R3:
S8->S9->S10
则对应的站点-路线关系表stop_route为
Stop
Route
Position
S1
R1
1
S2
R1
2
S3
R1
3
S4
R1
4
S5
R1
5
S6
R2
1
S7
R2
2
S2
R2
3
S8
R2
4
S8
R3
1
S9
R3
2
S10
R3
3
注:
Stop为站点名,Route为路线名,Position为站点在路线中的位置
2.直达乘车路线查询算法
基于表stop_route可以很方便实现直达乘车路线的查询,以下是用于查询直达乘车路线的存储过程InquiryT0:
createprocInquiryT0(StartStopvarchar(32),EndStopvarchar(32))
as
begin
select
sr1.Stopas启始站点,
sr2.Stopas目的站点,
sr1.Routeas乘坐线路,
sr2.Position-sr1.Positionas经过的站点数
from
stop_routesr1,
stop_routesr2
where
sr1.Route=sr2.Route
andsr1.Position andsr1.Stop=StartStop andsr2.Stop=EndStop end 3.查询换乘路线算法 (1)直达路线视图 直达路线视图可以理解为一存储了所有直达路线的表(如果两个站点之间存在直达路线,那么在直达路线视图中就有一行与之相对应)。 例如R1,R2,R3对应的RouteT0如下: 起点 终点 乘坐路线 站点数 S3 S4 R1 1 S3 S5 R1 2 S4 S5 R1 1 S1 S2 R1 1 S1 S3 R1 2 S1 S4 R1 3 S1 S5 R1 4 S2 S3 R1 1 S2 S4 R1 2 S2 S5 R1 3 S2 S8 R2 1 S6 S2 R2 2 S6 S7 R2 1 S6 S8 R2 3 S7 S2 R2 1 S7 S8 R2 2 S8 S10 R3 2 S8 S9 R3 1 S9 S10 R3 1 RouteT0定义如下: createviewRouteT0 as select sr1.StopasStartStop,--启始站点 sr2.StopasEndStop,--目的站点 sr1.RouteasRoute,--乘坐线路 sr2.Position-sr1.PositionasStopCount--经过的站点数 from stop_routesr1, stop_routesr2 where sr1.Route=sr2.Route andsr1.Position (2)换乘路线算法 显然,一条换乘路线由若干段直达路线组成(每段路线的终点与下一段路线的起点相同),因此,基于直达路线视图RouteT0可以很方便实现换乘查询,以下是实现一次换乘查询的存储过程InquiryT1: createprocInquiryT1(StartStopvarchar(32),EndStopvarchar(32)) as begin select r1.StartStopas启始站点, r1.Routeas乘坐路线1, r1.EndStopas中转站点, r2.Routeas乘坐路线2, r2.EndStopas目的站点, r1.StopCount+r2.StopCountas总站点数 from RouteT0r1, RouteT0r2 where r1.StartStop=StartStop andr1.EndStop=r2.StartStop andr2.EndStop=EndStop end 同理可以得到二次换乘的查询语句 createprocInquiryT2(StartStopvarchar(32),EndStopvarchar(32)) as begin select r1.StartStopas启始站点, r1.Routeas乘坐路线1, r1.EndStopas中转站点1, r2.Routeas乘坐路线2, r2.EndStopas中转站点2, r3.Routeas乘坐路线3, r3.EndStopas目的站点, r1.StopCount+r2.StopCount+r3.StopCountas总站点数 from RouteT0r1, RouteT0r2, RouteT0r3 where r1.StartStop=StartStop andr1.EndStop=r2.StartStop andr2.EndStop=r3.StartStop andr3.EndStop=EndStop end 4.测试 execInquiryT0'S1','S2' execInquiryT1'S1','S8' execInquiryT2'S1','S9' 运行结果: 公交车路线查询系统后台数据库设计--关联地名和站点 在《公交车路线查询系统后台数据库设计——查询算法》一文中,已经实现了查询站点到站点的路线查询算法,但是,现实中用户不一定使用站点进行查询,而是使用地名。 因此,公交车查询系统数据库必需记录地名与站点的对应关系,在查询时将地名映射为站点。 根据实际情况,某一地点附近通常有几个站点,因此,地名与站点之间是多对多的关系。 显然,只需创建一个地名站点关系表stop_spot(Stop,Spot)用于储存这个关系即可。 数据库关系图如下: 注: Route: 路线表 Stop: 站点表 Spot: 地名表 stop_route: 路线-站点关系表 stop_spot: 地名-站点关系表 1.路线和地名信息维护: 以下函数用于维护公交车路线和地名的相关信息 字符串分割函数(信息处理及路线查询的存储过程都需要使用到该函数): /* 函数功能: 将String以SplitChar为分隔点分割为字符串数组,结果保留在表变量中 例如SplitString('A/B','/')返回表: Valuevindex A1 B2 */ CREATEfunctionSplitString( Stringvarchar(2048), SplitCharchar ) returnsrestable( Valuevarchar(128), vindexint ) as begin declareindexint,unitvarchar(128),inextint,lenint,iint setindex=1 seti=1 setlen=len(String) whileindex<=len begin setinext=charindex(SplitChar,String,index) ifinext=0setinext=len+1 ifinext>index begin setunit=ltrim(rtrim(substring(String,index,inext-index))) ifunit<>'' begin insertintores(value,vindex)values(unit,i) seti=i+1 end end setindex=inext+1 end return end 插入新的公车路线: /* 插入新的公交车路线 Route: 路线名 Stops: 公交车经过的所有站点,站点用'-'隔开 */ CREATEprocInsertRoute(Routevarchar(32),Stops_Strvarchar(1024)) as begin declarestopstable(namevarchar(32),positionint) insertstops(name,position) selectValue,vIndexfromdbo.SplitString(Stops_Str,'-') begintrant1 savetransp1 --插入路线信息 insertintoRoute(name)values(Route) if(error<>0) begin rollbacktransp1 committrant1 raiserror('插入路线时发生错误',16,1) return end --插入不存在的站点 insertStop(name) selectdistinctnamefromstopssswherenamenotin(selectnamefromStop) if(error<>0) begin rollbacktransp1 committrant1 raiserror('插入路线时发生错误',16,1) return end insertstop_route(Stop,Route,Position) selectss.name,Route,ss.positionfromstopsss if(error<>0) begin rollbacktransp1 committrant1 raiserror('插入路线时发生错误',16,1) return end committrant1 end 插入新地名函数: /* 插入新地名 name: 地名 Stops: 地名附近的所有站点,多个站点用'/'隔开 Remark: 与地名相关的说明 */ CREATEprocInsertSpot( namevarchar(64), Stops_Strvarchar(1024), Remarkvarchar(1024) ) as begin declarestopstable(namevarchar(32)) insertstopsselectdistinctValuefromdbo.SplitString(Stops_Str,'/') declarenvarchar(32) setn='' selecttop1n=namefromstopsswherenamenotin(selectnamefromstop) if(n<>'') begin raiserror('站点%s不存在',16,1,n) return end insertintoSpot(name,remark)values(name,remark) insertstop_spot(Stop,Spot) selects.name,namefromstopss if(error<>0) begin raiserror('插入地点时发生错误',16,1) return end end 2.路线查询 在《公交车路线查询系统后台数据库设计——查询算法》一文中,使用储存过程InquiryT0,InquiryT1和InquiryT2实现了站点到站点的查询,但是地名可能对应多个站点,因此,当进行地点到地点的查询相当于站点集到站点集的查询。 因此,为了支持使用地名进行查询,将InquiryT0,InquiryT1和InquiryT2修改为站点集到站点集的查询: 直达路线查询: /* 查询站点StartStops到站点EndStops之间的直达乘车路线,多个站点用'/'分开,如: execInquiryT0'站点1/站点2','站点3/站点4' */ CREATEprocInquiryT0(StartStopsvarchar(32),EndStopsvarchar(32)) as begin declaress_tabtable(namevarchar(32)) declarees_tabtable(namevarchar(32)) insertss_tabselectValuefromdbo.SplitString(StartStops,'/') insertes_tabselectValuefromdbo.SplitString(EndStops,'/') if(exists(select*fromss_tabsst,es_tabestwheresst.name=est.name)) begin raiserror('起点集和终点集中含有相同的站点',16,1) return end select sst.nameas启始站点, est.nameas目的站点, r.Routeas乘坐线路, r.StopCountas经过的站点数 from ss_tabsst, es_tabest, RouteT0r where sst.name=r.StartStop andr.EndStop=est.name end 一次换乘查询: /* 查询站点StartStops到站点EndStops之间的一次换乘乘车路线,多个站点用'/'分开,如: execInquiryT1'站点1/站点2','站点3/站点4' */ CREATEprocInquiryT1(StartStopsvarchar(32),EndStopsvarchar(32)) as begin declaress_tabtable(namevarchar(32)) declarees_tabtable(namevarchar(32)) insertss_tabselectValuefromdbo.SplitString(StartStops,'/') insertes_tabselectValuefromdbo.SplitString(EndStops,'/') if(exists(select*fromss_tabsst,es_tabestwheresst.name=est.name)) begin raiserror('起点集和终点集中含有相同的站点',16,1) return end declarestopstable(namevarchar(32)) insertstopsselectnamefromss_tab insertstopsselectnamefromes_tab select sst.nameas起始站点, r1.Routeas乘坐路线1, r1.EndStopas中转站点1, r2.Routeas乘坐路线2, est.nameas目的站点, r1.StopCount+r2.StopCountas总站点数 from ss_tabsst, es_tabest, (select*fromRouteT0whereEndStopnotin(selectnamefromstops))r1, RouteT0r2 where sst.name=r1.StartStop andr1.EndStop=r2.StartStop andr2.EndStop=est.name andr1.Route<>r2.Route end 二次换乘查询: /* 查询站点StartStops到站点EndStops之间的二次换乘乘车路线,多个站点用'/'分开,如: execInquiryT2'站点1/站点2','站点3/站点4' */ CREATEprocInquiryT2(StartStopsvarchar(32),EndStopsvarchar(32)) as begin declaress_tabtable(namevarchar(32)) declarees_tabtable(namevarchar(32)) insertss_tabselectValuefromdbo.SplitString(StartStops,'/') insertes_tabselectValuefromdbo.SplitString(EndStops,'/') if(exists(select*fromss_tabsst,es_tabestwheresst.name=est.name)) begin raiserror('起点集和终点集中含有相同的站点',16,1) return end declarestopstable(namevarchar(32)) insertstopsselectnamefromss_tab insertstopsselectnamefromes_tab select r1.StartStopas启始站点, r1.Routeas乘坐路线1, r1.EndStopas中转站点1, r2.Routeas乘坐路线2, r2.EndStopas中转站点2, r3.Routeas乘坐路线3, r3.EndStopas目的站点, r1.StopCount+r2.StopCount+r3.StopCountas总站点数 from ss_tabsst, es_tabest, (select*fromRouteT0whereEndStopnotin(selectnamefromstops))r1, (select*fromRouteT0whereEndStopnotin(selectnamefromstops))r2, RouteT0r3 where sst.name=r1.StartStop andr1.EndStop=r2.StartStop andr2.EndStop=r3.StartStop andr3.EndStop=est.name andr1.Route<>r2.Route andr2.Route<>r3.Route andr3.Route<>r1.Route end 综合查询: /* 查询站点StartStops到站点EndStops之间的乘车路线,先查询直达路线, 如不存在,则查询一次换乘路线,如果直达和一次换乘均不存在,则查询二次换乘 多个站点用'/'分开,如: execInquiry'站点1/站点2','站点3/站点4' */ CREATEprocInquiry(StartStopsvarchar(32),EndStopsvarchar(32)) as begin execInquiryT0StartStops,EndStops if(rowcount=0) begin execInquiryT1StartStops,EndStops if(rowcount=0) begin execInquiryT2StartStops,EndStops end end end 如要进行地名到地名的路线查询,必需先调用GetStopsOfSpot获取地名对应的所有站点,在调用Inquiry进行查询。 获取地名对应的站点: /* 获取地名对应的站点,如有多个站点,用'/'隔开 */ CREATEfunctionGetStopsOfSpot(Spotvarchar(32)) returnsvarchar(1024) as begin declarestopsvarchar(1024) setstops='' selectstops=stops+'/'+stopfromstop_spotwhereSpot=Spot returnsubstring(stops,2,len(stops)-1) end 使用地名查询乘车路线示例: declarespsvarchar(1024),epsvarchar(1024) setsps=dbo.GetStopsOfSpot('起始地点名称') seteps=dbo.GetStopsOfSpot('目的地点名称') execInquirysps,eps 公交车路线查询系统后台数据库设计--引入步行路线 在《查询算法》和《关联地名和站点》两篇文章中,已经实现了通过地名或站点进行路线查询的算法,但是在现实中,从起点到终点不一定全程都是乘车,例如,有以下3条路线: R1: S1->S2->S3->S4->S5 R2: S6->S7->S2->S8 R3: S8->S9->S10 假如现在要从站点S1到S7,如果用Inquiry查询路线,显然没有合适的乘车方案。 但是S2和S7相距仅仅一个站的距离,可以用步行代替,因此可以先从S1乘坐R1到S2再步行到S7。 为了实现在乘车路线中插入步行路线,在数据库使用WalkRoute(StartStop,EndStop,Distance,Remark)(StartStop-起始站点,EndStop-目的站点,Distance-距离,Remark-备注)储存距离较近的两个站点。 加入表WalkRoute后,查询算法也要作相应的修改,其实WalkRoute和RouteT0很相似,因此只需把WalkRoute看成是特殊的直达线路即可,修改后的InqueryT1如下: /* 查询站点StartStops到站
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 公交车 路线 查询 系统 后台数据库 设计 说明