今天在尝试编写地铁换乘查询时,在b站上发现了一个sql语句实现地铁换乘查询的案例,于是开始学习本案例。此案例的数据表结构为:
![]()
在案例讲解中,只在sql语句就实现了换乘查询的功能以一号线的王府井到二号线的积水潭为例
WITH RECURSIVE transfer (start_station, stop_station, stops, path) AS ( SELECT station_name, next_station,1, CAST(CONCAT(line_name,station_name ,'->', line_name,next_station) AS CHAR(1000)) FROM bj_subway WHERE station_name='王府井'UNION ALL SELECT p.start_station, e.next_station, stops+1, CONCAT(p.path,'->', e.line_name, e.next_station) FROM transfer p JOIN bj_subway e ON p.stop_station= e.station_name AND (INSTR(p.path, e.next_station) =0))SELECT* FROM transfer WHERE stop_station ='积水潭';--OracleWITH transfer (start_station, stop_station, stops, path) AS ( SELECT station_name, next_station,1, line_name||station_name||'->'||line_name||next_station FROM bj_subway WHERE station_name='王府井'UNION ALL SELECT p.start_station, e.next_station, stops+1, p.path||'->'||e.line_name||e.next_station FROM transfer p JOIN bj_subway e ON p.stop_station= e.station_name AND (INSTR(p.path, e.next_station) =0))SELECT* FROM transfer WHERE stop_station ='积水潭';--SQL ServerWITH transfer(start_station, stop_station, stops, paths) AS (SELECT station_name, next_station,1stops, CAST(concat(line_name,station_name,'->',line_name,next_station) AS varchar(1000)) AS pathsFROM bj_subwayWHERE station_name='王府井'UNION ALL SELECT t.start_station, s.next_station, stops+1, CAST(concat(paths,'->', s.line_name, s.next_station) AS varchar(1000))FROM transfer tJOIN bj_subway s ON (t.stop_station= s.station_name AND charindex(s.next_station, paths)=0))SELECT*FROM transferWHERE stop_station='积水潭';--PostgreSQLWITH RECURSIVE transfer (start_station, stop_station, stops, path) AS ( SELECT station_name, next_station,1, ARRAY[station_name::text, next_station::text] FROM bj_subway WHERE station_name='王府井'UNION ALL SELECT p.start_station, e.next_station, stops+1, p.path ||ARRAY[e.next_station::text] FROM transfer p JOIN bj_subway e ON p.stop_station= e.station_name AND NOT e.next_station =ANY(p.path))SELECT* FROM transfer WHERE stop_station ='积水潭';--SQLiteWITH RECURSIVE transfer(start_station, stop_station, stops, paths) AS (SELECT station_name, next_station,1stops, line_name||station_name||'->'||line_name||next_station AS pathsFROM bj_subwayWHERE station_name='王府井'UNION ALL SELECT t.start_station, s.next_station, stops+1, paths||'->'||s.line_name||s.next_stationFROM transfer tJOIN bj_subway s ON (t.stop_station= s.station_name AND instr(paths, s.next_station)=0))SELECT*FROM transferWHERE stop_station='积水潭';Footer 在学习本案例时,我有些看不明白,并不理解为啥能够在SQL语句里面实现递归,但是通过讲解,明白了实质为深度查询,其实就是在利用算法来实现本功能,实际应用比较困难,写此博客来提供一种思路。

在案例讲解中,只在sql语句就实现了换乘查询的功能以一号线的王府井到二号线的积水潭为例
WITH RECURSIVE transfer (start_station, stop_station, stops, path) AS ( SELECT station_name, next_station,1, CAST(CONCAT(line_name,station_name ,'->', line_name,next_station) AS CHAR(1000)) FROM bj_subway WHERE station_name='王府井'UNION ALL SELECT p.start_station, e.next_station, stops+1, CONCAT(p.path,'->', e.line_name, e.next_station) FROM transfer p JOIN bj_subway e ON p.stop_station= e.station_name AND (INSTR(p.path, e.next_station) =0))SELECT* FROM transfer WHERE stop_station ='积水潭';--OracleWITH transfer (start_station, stop_station, stops, path) AS ( SELECT station_name, next_station,1, line_name||station_name||'->'||line_name||next_station FROM bj_subway WHERE station_name='王府井'UNION ALL SELECT p.start_station, e.next_station, stops+1, p.path||'->'||e.line_name||e.next_station FROM transfer p JOIN bj_subway e ON p.stop_station= e.station_name AND (INSTR(p.path, e.next_station) =0))SELECT* FROM transfer WHERE stop_station ='积水潭';--SQL ServerWITH transfer(start_station, stop_station, stops, paths) AS (SELECT station_name, next_station,1stops, CAST(concat(line_name,station_name,'->',line_name,next_station) AS varchar(1000)) AS pathsFROM bj_subwayWHERE station_name='王府井'UNION ALL SELECT t.start_station, s.next_station, stops+1, CAST(concat(paths,'->', s.line_name, s.next_station) AS varchar(1000))FROM transfer tJOIN bj_subway s ON (t.stop_station= s.station_name AND charindex(s.next_station, paths)=0))SELECT*FROM transferWHERE stop_station='积水潭';--PostgreSQLWITH RECURSIVE transfer (start_station, stop_station, stops, path) AS ( SELECT station_name, next_station,1, ARRAY[station_name::text, next_station::text] FROM bj_subway WHERE station_name='王府井'UNION ALL SELECT p.start_station, e.next_station, stops+1, p.path ||ARRAY[e.next_station::text] FROM transfer p JOIN bj_subway e ON p.stop_station= e.station_name AND NOT e.next_station =ANY(p.path))SELECT* FROM transfer WHERE stop_station ='积水潭';--SQLiteWITH RECURSIVE transfer(start_station, stop_station, stops, paths) AS (SELECT station_name, next_station,1stops, line_name||station_name||'->'||line_name||next_station AS pathsFROM bj_subwayWHERE station_name='王府井'UNION ALL SELECT t.start_station, s.next_station, stops+1, paths||'->'||s.line_name||s.next_stationFROM transfer tJOIN bj_subway s ON (t.stop_station= s.station_name AND instr(paths, s.next_station)=0))SELECT*FROM transferWHERE stop_station='积水潭';Footer 在学习本案例时,我有些看不明白,并不理解为啥能够在SQL语句里面实现递归,但是通过讲解,明白了实质为深度查询,其实就是在利用算法来实现本功能,实际应用比较困难,写此博客来提供一种思路。