-- Tabla donde define cada una de las distancias entre dos localidades DROP TABLE IF EXISTS public.etapas CASCADE; CREATE TABLE public.etapas ( from_city_name CHARACTER VARYING(120) NOT NULL , to_city_name CHARACTER VARYING(120) NOT NULL , km_distance_num NUMERIC(5,2) NOT NULL , CONSTRAINT pk_route PRIMARY KEY (from_city_name, to_city_name) ); -- Carga de datos INSERT INTO public.etapas VALUES ('Saint Jean Pied de Port','Roncesvalles',25.7), ('Somport','Jaca',30.5), ('Roncesvalles','Zubiri',21.5), ('Jaca','Arrés',25), ('Zubiri','Pamplona/Iruña',20.4), ('Arrés','Ruesta',28.7), ('Pamplona/Iruña','Puente la Reina/Gares',24), ('Ruesta','Sangüesa',21.8), ('Puente la Reina/Gares','Estella/Lizarra',22), ('Sangüesa','Monreal',27.25), ('Estella/Lizarra','Torres del Río',29), ('Monreal','Puente la Reina/Gares',31.1), ('Torres del Río','Logroño',20), ('Logroño','Nájera',29.6), ('Nájera','Santo Domingo de la Calzada',21), ('Santo Domingo de la Calzada','Belorado',22.7), ('Belorado','Agés',27.4), ('Agés','Burgos',23), ('Burgos','Hontanas',31.1), ('Hontanas','Boadilla del Camino',28.5), ('Boadilla del Camino','Carrión de los Condes',24.6), ('Carrión de los Condes','Terradillos de los Templarios',26.6), ('Terradillos de los Templarios','El Burgo Ranero',30.6), ('El Burgo Ranero','León',37.1), ('León','San Martín del Camino',25.9), ('San Martín del Camino','Astorga',24.2), ('Astorga','Foncebadón',25.9), ('Foncebadón','Ponferrada',27.3), ('Ponferrada','Villafranca del Bierzo',24.1), ('Villafranca del Bierzo','O Cebreiro',28.4), ('O Cebreiro','Triacastela',21.1), ('Triacastela','Sarria',18.3), ('Sarria','Portomarín',22.4), ('Portomarín','Palas de Rei',25), ('Palas de Rei','Arzúa',28.8), ('Arzúa','Pedrouzo',19.1), ('Pedrouzo','Santiago de Compostela',20), ('Bayona','Ustaritz',14.3), ('Ustaritz','Urdax',21.2), ('Urdax','Elizondo',18.8), ('Elizondo','Berroeta',9.7), ('Berroeta','Olagüe',20.4), ('Olagüe','Pamplona/Iruña',25), ('Irún','Hernani',26.6), ('Hernani','Tolosa',18.9), ('Tolosa','Zerain',33), ('Zerain','Salvatierra/Agurain',28), ('Salvatierra/Agurain','Vitoria/Gasteiz',27.4), ('Vitoria/Gasteiz','La Puebla de Arganzón',18.5), ('La Puebla de Arganzón','Haro',31), ('Haro','Santo Domingo de la Calzada',20), ('Bayona','Irún',33.8), ('Tolosa','Zegama',37.9), ('Zegama','Salvatierra/Agurain',20.1), ('La Puebla de Arganzón','Miranda del Ebro',22.3), ('Miranda del Ebro','Pancorbo',16.7), ('Pancorbo','Briviesca',23.4), ('Briviesca','Monasterio de Rodilla',19.8), ('Monasterio de Rodilla','Burgos',28.5); -- Se define la función recursiva que ira recorriendo las localidades WITH RECURSIVE f_recursiva AS ( -- FASE No iterativa define el escenario de partida SELECT to_city_name, from_city_name, 0.0 + km_distance_num AS distancia, 1 AS etapas, CAST(from_city_name || '->' || to_city_name As varchar(1000)) As resultado FROM public.etapas WHERE from_city_name = 'Bayona' -- FASES Iterativas, define las modificaciones que suceden en cada uno de las iteraciones. UNION ALL SELECT tab.to_city_name, recur.from_city_name, recur.distancia + tab.km_distance_num AS distancia, recur.etapas + 1 AS etapas, CAST( recur.resultado || '->' || tab.to_city_name As varchar(1000)) As resultado FROM public.etapas As tab INNER JOIN f_recursiva AS recur ON (tab.from_city_name = recur.to_city_name) ) SELECT DISTINCT from_city_name AS "Desde", to_city_name AS "Hasta", resultado, etapas, distancia FROM f_recursiva WHERE to_city_name = 'Santiago de Compostela' ORDER BY distancia ASC;
Lindo ejemplo, muchas gracias.
Espectacular el ejemplo …. una pregunta, cómo se podría generar «resultado» con el orden inverso , sin modificar tablas, solo mostrar las etapas desde la última hacia atrás, en la select final, alguna sugerencia?
Gracias!!!!
Buenas Fredd, entiendo que te saldría más a cuenta hacer una consulta que cambiase la tabla base de orden de origen a destino y aplicaría el mismo algoritmo.