公交车路线查询系统后台数据库设计.doc_第1页
公交车路线查询系统后台数据库设计.doc_第2页
公交车路线查询系统后台数据库设计.doc_第3页
公交车路线查询系统后台数据库设计.doc_第4页
公交车路线查询系统后台数据库设计.doc_第5页
已阅读5页,还剩41页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

公交车路线查询系统后台数据库设计-查询算法1. 公交车路线信息在数据库中的存储方式显然,如果在数据库中简单的使用表bus_route(路线名,路线经过的站点,费用)来保存公交车路线的线路信息,则很难使用查询语句实现乘车线路查询,因此,应该对线路的信息进行处理后再保存到数据库中,笔者使用的方法是用站点-路线关系表stop_route(站点,路线名,站点在路线中的位置)来存储公交车路线,例如,如果有以下3条路线R1: S1-S2-S3-S4-S5R2: S6-S7-S2-S8R3: S8-S9-S10则对应的站点-路线关系表stop_route为StopRoutePositionS1R11S2R12S3R13S4R14S5R15S6R21S7R22S2R23S8R24S8R31S9R32S10R33注:Stop为站点名,Route为路线名,Position为站点在路线中的位置2.直达乘车路线查询算法基于表stop_route可以很方便实现直达乘车路线的查询,以下是用于查询直达乘车路线的存储过程InquiryT0:create proc InquiryT0(StartStop varchar(32),EndStop varchar(32)asbegin select sr1.Stop as 启始站点, sr2.Stop as 目的站点, sr1.Route as 乘坐线路, sr2.Position-sr1.Position as 经过的站点数 from stop_route sr1, stop_route sr2 where sr1.Route=sr2.Route and sr1.Positionsr2.Position and sr1.Stop=StartStop and sr2.Stop=EndStopend3.查询换乘路线算法(1)直达路线视图直达路线视图可以理解为一张存储了所有直达路线的表(如果两个站点之间存在直达路线,那么在直达路线视图中就有一行与之相对应)。例如R1,R2,R3对应的RouteT0如下:起点终点乘坐路线站点数S3S4R11S3S5R12S4S5R11S1S2R11S1S3R12S1S4R13S1S5R14S2S3R11S2S4R12S2S5R13S2S8R21S6S2R22S6S7R21S6S8R23S7S2R21S7S8R22S8S10R32S8S9R31S9S10R31RouteT0定义如下:create view RouteT0as select sr1.Stop as StartStop, -启始站点 sr2.Stop as EndStop, -目的站点 sr1.Route as Route, -乘坐线路 sr2.Position-sr1.Position as StopCount -经过的站点数 from stop_route sr1, stop_route sr2 where sr1.Route=sr2.Route and sr1.Positionsr2.Position (2)换乘路线算法显然,一条换乘路线由若干段直达路线组成(每段路线的终点与下一段路线的起点相同),因此,基于直达路线视图RouteT0可以很方便实现换乘查询,以下是实现一次换乘查询的存储过程InquiryT1:create proc InquiryT1(StartStop varchar(32),EndStop varchar(32)asbegin select r1.StartStop as 启始站点, r1.Route as 乘坐路线1, r1.EndStop as 中转站点, r2.Route as 乘坐路线2, r2.EndStop as 目的站点, r1.StopCount+r2.StopCount as 总站点数 from RouteT0 r1, RouteT0 r2 where r1.StartStop=StartStop and r1.EndStop=r2.StartStop and r2.EndStop=EndStopend同理可以得到二次换乘的查询语句 create proc InquiryT2(StartStop varchar(32),EndStop varchar(32)asbegin select r1.StartStop as 启始站点, r1.Route as 乘坐路线1, r1.EndStop as 中转站点1, r2.Route as 乘坐路线2, r2.EndStop as 中转站点2, r3.Route as 乘坐路线3, r3.EndStop as 目的站点, r1.StopCount+r2.StopCount+r3.StopCount as 总站点数 from RouteT0 r1, RouteT0 r2, RouteT0 r3 where r1.StartStop=StartStop and r1.EndStop=r2.StartStop and r2.EndStop=r3.StartStop and r3.EndStop=EndStopend 4.测试exec InquiryT0 S1,S2exec InquiryT1 S1,S8exec InquiryT2 S1,S9运行结果:公交车路线查询系统后台数据库设计-关联地名和站点在公交车路线查询系统后台数据库设计查询算法一文中,已经实现了查询站点到站点的路线查询算法,但是,现实中用户不一定使用站点进行查询,而是使用地名。因此,公交车查询系统数据库必需记录地名与站点的对应关系,在查询时将地名映射为站点。根据实际情况,某一地点附近通常有几个站点,因此,地名与站点之间是多对多的关系。显然,只需创建一个地名站点关系表stop_spot(Stop,Spot)用于储存这个关系即可。数据库关系图如下:注:Route:路线表 Stop:站点表 Spot:地名表 stop_route: 路线-站点关系表 stop_spot:地名-站点关系表1.路线和地名信息维护:以下函数用于维护公交车路线和地名的相关信息字符串分割函数(信息处理及路线查询的存储过程都需要使用到该函数) : /*函数功能:将String以SplitChar为分隔点分割为字符串数组,结果保留在表变量中例如SplitString(A/B,/)返回表:Value vindexA 1B 2*/CREATE function SplitString( String varchar(2048), SplitChar char)returns res table( Value varchar(128), vindex int)asbegin declare index int,unit varchar(128),inext int,len int,i int set index=1 set i=1 set len=len(String) while indexindex begin set unit=ltrim(rtrim(substring(String,index,inext-index) if unit begin insert into res (value,vindex) values (unit,i) set i=i+1 end end set index=inext+1 end returnend插入新的公车路线:/*插入新的公交车路线Route:路线名Stops:公交车经过的所有站点,站点用-隔开*/CREATE proc InsertRoute(Route varchar(32),Stops_Str varchar(1024)asbegin declare stops table(name varchar(32),position int) insert stops(name,position) select Value,vIndex from dbo.SplitString(Stops_Str,-) begin tran t1 save tran sp1 -插入路线信息 insert into Route (name) values (Route) if(error0) begin rollback tran sp1 commit tran t1 raiserror(插入路线时发生错误,16,1) return end -插入不存在的站点 insert Stop(name) select distinct name from stops ss where name not in (select name from Stop) if(error0) begin rollback tran sp1 commit tran t1 raiserror(插入路线时发生错误,16,1) return end insert stop_route(Stop,Route,Position) select ,Route,ss.position from stops ss if(error0) begin rollback tran sp1 commit tran t1 raiserror(插入路线时发生错误,16,1) return end commit tran t1end插入新地名函数:/*插入新地名name:地名Stops:地名附近的所有站点,多个站点用/隔开Remark:与地名相关的说明*/CREATE proc InsertSpot(name varchar(64),Stops_Str varchar(1024),Remark varchar(1024)asbegin declare stops table(name varchar(32) insert stops select distinct Value from dbo.SplitString(Stops_Str,/) declare n varchar(32) set n= select top 1 n=name from stops s where name not in (select name from stop) if(n) begin raiserror (站点%s不存在,16,1,n) return end insert into Spot (name,remark) values (name,remark) insert stop_spot(Stop,Spot) select ,name from stops s if(error0) begin raiserror (插入地点时发生错误,16,1) return endend 2.路线查询在公交车路线查询系统后台数据库设计查询算法一文中,使用储存过程InquiryT0,InquiryT1和InquiryT2实现了站点到站点的查询,但是地名可能对应多个站点,因此,当进行地点到地点的查询相当于站点集到站点集的查询。因此,为了支持使用地名进行查询,将InquiryT0,InquiryT1和InquiryT2修改为站点集到站点集的查询:直达路线查询:/*查询站点StartStops到站点EndStops之间的直达乘车路线,多个站点用/分开,如:exec InquiryT0 站点1/站点2,站点3/站点4*/CREATE proc InquiryT0(StartStops varchar(32),EndStops varchar(32)asbegin declare ss_tab table(name varchar(32) declare es_tab table(name varchar(32) insert ss_tab select Value from dbo.SplitString(StartStops,/) insert es_tab select Value from dbo.SplitString(EndStops,/) if(exists(select * from ss_tab sst,es_tab est where =) begin raiserror (起点集和终点集中含有相同的站点,16,1) return end select as 启始站点, as 目的站点, r.Route as 乘坐线路, r.StopCount as 经过的站点数 from ss_tab sst, es_tab est, RouteT0 r where =r.StartStop and r.EndStop=end一次换乘查询:/*查询站点StartStops到站点EndStops之间的一次换乘乘车路线,多个站点用/分开,如:exec InquiryT1 站点1/站点2,站点3/站点4*/CREATE proc InquiryT1(StartStops varchar(32),EndStops varchar(32)asbegin declare ss_tab table(name varchar(32) declare es_tab table(name varchar(32) insert ss_tab select Value from dbo.SplitString(StartStops,/) insert es_tab select Value from dbo.SplitString(EndStops,/) if(exists(select * from ss_tab sst,es_tab est where =) begin raiserror (起点集和终点集中含有相同的站点,16,1) return end declare stops table(name varchar(32) insert stops select name from ss_tab insert stops select name from es_tab select as 起始站点, r1.Route as 乘坐路线1, r1.EndStop as 中转站点1, r2.Route as 乘坐路线2, as 目的站点, r1.StopCount+r2.StopCount as 总站点数 from ss_tab sst, es_tab est, (select * from RouteT0 where EndStop not in (select name from stops) r1, RouteT0 r2 where =r1.StartStop and r1.EndStop=r2.StartStop and r2.EndStop= and r1.Router2.Routeend二次换乘查询:/*查询站点StartStops到站点EndStops之间的二次换乘乘车路线,多个站点用/分开,如:exec InquiryT2 站点1/站点2,站点3/站点4*/CREATE proc InquiryT2(StartStops varchar(32),EndStops varchar(32)asbegin declare ss_tab table(name varchar(32) declare es_tab table(name varchar(32) insert ss_tab select Value from dbo.SplitString(StartStops,/) insert es_tab select Value from dbo.SplitString(EndStops,/) if(exists(select * from ss_tab sst,es_tab est where =) begin raiserror (起点集和终点集中含有相同的站点,16,1) return end declare stops table(name varchar(32) insert stops select name from ss_tab insert stops select name from es_tab select r1.StartStop as 启始站点, r1.Route as 乘坐路线1, r1.EndStop as 中转站点1, r2.Route as 乘坐路线2, r2.EndStop as 中转站点2, r3.Route as 乘坐路线3, r3.EndStop as 目的站点, r1.StopCount+r2.StopCount+r3.StopCount as 总站点数 from ss_tab sst, es_tab est, (select * from RouteT0 where EndStop not in (select name from stops) r1, (select * from RouteT0 where EndStop not in (select name from stops) r2, RouteT0 r3 where =r1.StartStop and r1.EndStop=r2.StartStop and r2.EndStop=r3.StartStop and r3.EndStop= and r1.Router2.Route and r2.Router3.Route and r3.Router1.Routeend综合查询:/*查询站点StartStops到站点EndStops之间的乘车路线,先查询直达路线,如不存在,则查询一次换乘路线,如果直达和一次换乘均不存在,则查询二次换乘多个站点用/分开,如:exec Inquiry 站点1/站点2,站点3/站点4*/CREATE proc Inquiry(StartStops varchar(32),EndStops varchar(32)asbegin exec InquiryT0 StartStops,EndStops if(rowcount=0) begin exec InquiryT1 StartStops,EndStops if(rowcount=0) begin exec InquiryT2 StartStops,EndStops end endend如要进行地名到地名的路线查询,必需先调用GetStopsOfSpot获取地名对应的所有站点,在调用Inquiry进行查询。获取地名对应的站点:/*获取地名对应的站点,如有多个站点,用/隔开*/CREATE function GetStopsOfSpot(Spot varchar(32)returns varchar(1024)asbegin declare stops varchar(1024) set stops= select stops=stops+/+stop from stop_spot where Spot=Spot return substring(stops,2,len(stops)-1)end 使用地名查询乘车路线示例:declare sps varchar(1024),eps varchar(1024)set sps=dbo.GetStopsOfSpot(起始地点名称)set eps=dbo.GetStopsOfSpot(目的地点名称)exec Inquiry sps,eps公交车路线查询系统后台数据库设计-引入步行路线在查询算法和关联地名和站点两篇文章中,已经实现了通过地名或站点进行路线查询的算法,但是在现实中,从起点到终点不一定全程都是乘车,例如,有以下3条路线:R1: S1-S2-S3-S4-S5R2: S6-S7-S2-S8R3: 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到站点EndStops之间的一次换乘乘车路线,多个站点用/分开,如: exec InquiryT1 站点1/站点2,站点3/站点4 */ CREATE proc InquiryT1(StartStops varchar(32),EndStops varchar(32) as begin declare ss_tab table(name varchar(32) declare es_tab table(name varchar(32) insert ss_tab select Value from dbo.SplitString(StartStops,/) insert es_tab select Value from dbo.SplitString(EndStops,/) if(exists(select * from ss_tab sst,es_tab est where =) begin raiserror (起点集和终点集中含有相同的站点,16,1) return end declare stops table(name varchar(32) insert stops select name from ss_tab insert stops select name from es_tab declare result table( StartStop varchar(32), Route1 varchar(256), TransStop varchar(32), Route2 varchar(256), EndStop varchar(32), StopCount int ) declare count int set count=0 -查询步行-乘车路线 insert result select as StartStop, 从+r1.StartStop+步行到+r1.EndStop as Route1, r1.EndStop as TransStop, r2.Route as Route2, as EndStop, r2.StopCount as StopCount from ss_tab sst, es_tab est, (select * from WalkRoute where EndStop not in (select name from stops) r1, RouteT0 r2 where =r1.StartStop and r1.EndStop=r2.StartStop and r2.EndStop= order by r2.StopCount set count=rowcount -查询乘车-步行路线 insert result select as StartStop, r1.Route as Route1, r1.EndStop as TransStop, 从+r2.StartStop+步行到+r2.EndStop as Route2, as EndStop, r1.StopCount as StopCount from ss_tab sst, es_tab est, RouteT0 r1, (select * from WalkRoute where StartStop not in (select name from stops) r2 where =r1.StartStop and r1.EndStop=r2.StartStop and r2.EndStop= order by r1.StopCount set count=count+rowcount if(count=0) begin -查询乘车-乘车路线 insert result select as StartStop, r1.Route as Route1, r1.EndStop as TransStop, r2.Route as Route2, as EndStop, r1.StopCount+r2.StopCount as StopCount from ss_tab sst, es_tab est, (select * from RouteT0 where EndStop not in (select name from stops) r1, RouteT0 r2 where =r1.StartStop and r1.EndStop=r2.StartStop and r2.EndStop= and r1.Router2.Route order by r1.StopCount+r2.StopCount end select StartStop as 起始站点, Route1 as 路线1, TransStop as 中转站点, Route2 as 路线2, EndStop as 目的站点, StopCount as 总站点数 from result end公交车路线查询系统后台数据库设计-换乘算法改进与优化在查询算法一文中已经实现了换乘算法,但是,使用存储过程InquiryT2查询从“东圃镇”到“车陂路口”的乘车路线时,发现居然用了5分钟才查找出结果,这样的效率显然不适合实际应用。因此,有必要对原有的换乘算法进行优化和改进。在本文中,将给出一种改进的换乘算法,相比原有的算法,改进后的算法功能更强,效率更优。1. “压缩”RouteT0假设RouteT0有以下几行如下图所示,当查询S1到S4的二次换乘路线时,将会产生324=24个结果从图中可以看出,第1段路线中的3条线路的起点和站点都相同(第2、3段路线也是如此),事实上,换乘查询中关心的是两个站点之间有无线路可通,而不关心是乘坐什么路线,因此,可以将RouteT0压缩为:如下图所示,压缩后,查询结果有原来的24条合并1组查询结果为:那么,为什么要对视图RouteT0进行压缩呢,原因如下:(1)RouteT0是原有换乘算法频繁使用的视图,因此,RouteT0的数据量直接影响到查询的效率,压缩RouteT0可以减少RouteT0的数据量,加速查询效率。(2)压缩RouteT0后,将中转站点相同的路线合并为1组,加速了对结果集排序的速度。2.视图GRouteT0在数据库中,将使用GRouteT0来描述压缩的RouteT0,由于本文使用的数据库的关系图与查询算法中有所不同,在给出GRouteT0的代码前,先说明一下:主要的改变是Stop_Route使用了整数型的RouteKey和StopKey引用Route和Stop,而不是用路线名和站点名。GRouteT0定义如下: create view GRouteT0asselect StartStopKey, EndStopKey, min(StopCount) as MinStopCount, max(StopCount) as MaxStopCountfrom RouteT0group by StartStopKey,EndStopKey 注意,视图GRouteT0不仅有StartStopKey和EndStopKey列,还有MinStopCount列,MinStopCount是指从StartStop到EndStop的最短线路的站点数。例如:上述RouteT0对应的GRouteT0为:3.二次查询算法以下是二次换乘查询的存储过程GInquiryT2的代码,该存储过程使用了临时表来提高查询效率: GInquiryT2/*查询站点StartStops到站点EndStops之间的二次换乘乘车路线,多个站点用/分开,结果以分组方式给出,如:exec InquiryT2 站点1/站点2,站点3/站点4*/CREATE proc GInquiryT2( StartStops varchar(2048), EndStops varchar(2048)asbegin declare ss_tab table(StopKey int) declare es_tab table(StopKey int) insert ss_tab select distinct Stop.StopKey from dbo.SplitString(StartStops,/) sn,Stop where sn.Value=Stop.StopName insert es_tab select distinct Stop.StopKey from dbo.SplitString(EndStops,/) sn,Stop where sn.Value=Stop.StopName if(exists(select top 1 * from ss_tab sst,es_tab est where sst.StopKey=est.StopKey) begin raiserror (起点集和终点集中含有相同的站点,16,1) return end declare stops table(StopKey int) insert stops select StopKey from ss_tab insert stops select StopKey from es_tab print = print 筛选出第1段乘车路线 print - set statistics time on - -筛选出第1段乘车路线,保存到临时表#R1中 select * into #R1 from GRouteT0 where StartStopKey in (select StopKey from ss_tab) and EndStopKey not in (Select StopKey from stops) order by StartStopKey,EndStopKey -在临时表#R1上创建索引 create index index1 on #R1(StartStopKey,EndStopKey) - set statistics time off print = print 筛选出第3段乘车路线 print - set statistics time on - -筛选出第3段乘车路线,保存到临时表#R3中 select * into #R3 from

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论