Se puede hacer con un select ?

27/10/2009 - 05:20 por Nelson | Informe spam
Quitando los detalles tengo una tabla con algo como esto:

Rutas
-
parada1, parada2

A B
A C
B D
D E

Si me piden sacar la "ruta" desde A hasta E, debe sacarme un varchar con
'A-B-D-E'.

Se que lo puedo hacer con un cursor recorriendo los registros pero me han
dicho que no se aconseja.

Hay manera de hacerlo con un select ? alguna orientacion que me puedan dar
pues no lo entiendo

Grax

ss2008

Preguntas similare

Leer las respuestas

#6 Carlos M. Calvelo
27/10/2009 - 18:34 | Informe spam
Hola Nelson,

On 27 okt, 05:20, "Nelson" wrote:
Quitando los detalles tengo una tabla con algo como esto:

Rutas
-
parada1, parada2

A      B
A      C
B      D
D      E

Si me piden sacar la "ruta" desde A hasta E, debe sacarme un varchar con
'A-B-D-E'.

Se que lo puedo hacer con un cursor recorriendo los registros pero me han
dicho que no se aconseja.

Hay manera de hacerlo con un select ?  alguna orientacion que me puedan dar
pues no lo entiendo




Aquí abajo te dejo un ejemplo. Si quieres hacer pruebas
con él prueba también otros orígenes y destinos.
Quizás sea conveniente dibujar un grafo de la conexiones.
O prepara tu otro grafo y... ten cuidado con los ciclos! ;-)

set nocount on

declare @Conexiones table(A char(1), B char(1))
insert into @Conexiones values ('A','B')
insert into @Conexiones values ('A','C')
insert into @Conexiones values ('A','D')
insert into @Conexiones values ('B','E')
insert into @Conexiones values ('C','F')
insert into @Conexiones values ('C','G')
insert into @Conexiones values ('E','G')
insert into @Conexiones values ('F','E')
insert into @Conexiones values ('F','H')
insert into @Conexiones values ('G','I')
insert into @Conexiones values ('H','I')


declare @origen char(1), @destino char(1)
set @origen = 'A'
set @destino = 'I'

;
with Viajes as
(
select
cast(A+'-'+B as varchar(max)) Ruta,
B PuntoFinal,
2 #Puntos
from @Conexiones
where A = @origen
union all
select
cast(V.ruta+'-'+C.B as varchar(max)) Ruta,
C.B PuntoFinal,
#Puntos+1 #Puntos
from Viajes V join @Conexiones C on V.PuntoFinal = C.A
)
select Ruta, #Puntos
from Viajes
where PuntoFinal = @destino


Saludos,
Carlos
Respuesta Responder a este mensaje
#7 Carlos M. Calvelo
27/10/2009 - 19:02 | Informe spam
Hola Nelson,

Puedes añadir también una condición en la segunda
consulta del with, como indico abajo, para evitar seguir
haciendo joins innecesarios cuando ya se ha llegado
al destino.


On 27 okt, 18:34, "Carlos M. Calvelo" wrote:

set nocount on

declare @Conexiones table(A char(1), B char(1))
insert into @Conexiones values ('A','B')
insert into @Conexiones values ('A','C')
insert into @Conexiones values ('A','D')
insert into @Conexiones values ('B','E')
insert into @Conexiones values ('C','F')
insert into @Conexiones values ('C','G')
insert into @Conexiones values ('E','G')
insert into @Conexiones values ('F','E')
insert into @Conexiones values ('F','H')
insert into @Conexiones values ('G','I')
insert into @Conexiones values ('H','I')

declare @origen char(1), @destino char(1)
set @origen  = 'A'
set @destino = 'I'

;
with Viajes as
(
  select
    cast(A+'-'+B as varchar(max)) Ruta,
    B PuntoFinal,
    2 #Puntos
  from @Conexiones
  where A = @origen
  union all
  select
    cast(V.ruta+'-'+C.B as varchar(max)) Ruta,
    C.B PuntoFinal,
    #Puntos+1 #Puntos
  from Viajes V join @Conexiones C on V.PuntoFinal = C.A



where C.A <> @destino

)
select Ruta, #Puntos
from Viajes
where PuntoFinal = @destino




Saludos,
Carlos
Respuesta Responder a este mensaje
#8 Nelson
27/10/2009 - 21:14 | Informe spam
O sea ensayar con el primer origen "A". Si no puedo llegar a "E" a través
de él, pues pruebo con otro origen "A" hasta que encuentre uno que me
permita llegar a "E" o hasta que haberlos recorrido todas las rutas que
parten de "A".

"Carlos Sacristan" wrote in message
news:
¿¿?? No te entiendo...

"Caminar sobre el agua y desarrollar software a partir de unas
especificaciones es fácil, si ambas están congeladas."
Edward V. Berard, ingeniero informático


"Nelson" wrote in message
news:
Exacto, debe ser una técnica de ensayo y error, recursivo.

"Carlos Sacristan" wrote in message
news:
Entonces nos faltan datos para saber qué ruta coger cuando hay varios
comienzos; en realidad lo mismo pasaría con el resto de "paradas", es
necesario identificar la ruta a seguir.

"Caminar sobre el agua y desarrollar software a partir de unas
especificaciones es fácil, si ambas están congeladas."
Edward V. Berard, ingeniero informático


"Nelson" wrote in message
news:
En realidad A-C no es erróneo, es solo otra posibilidad similar a A-B.
Es algo parecido a rutas de vuelo: ejemplo sale un vuelo desde el punto
A al C pero sale otro desde A a B, and so on..

Si me pidieran la ruta de A hasta C pues el resultado sería simplemente
A-C.
Pero como me lo piden hasta E, como el ejemplo, tengo que "irme" por
"B".

De todas maneras gracias por la ayuda, creo que me sirve de pie para
resolverlo, voy a analizarlo ya que en realidad no había utilizado ese
tipo de instrucción con WITH (CTE, segun vi en la ayuda).
Sé que es recursivo pero me confunde la sintaxis para interpretarlo en
relacion a lo que uno entiende como funcion recursiva.

Gracias


"Carlos Sacristan" wrote in message
news:%
Con los datos que has enviado la ruta no tiene por qué ser esa. Fíjate
que en "parada1" aparece dos veces "A", así que la ruta podría ser A-C
o A-B-D-E

Suponiendo que el registro A-C es erróneo, una solución podría ser:

***************************************************************************************

declare @inicio char(1)
set @inicio = 'A'
;WITH viaje(desde, hasta, numParada) AS
(
SELECT Desde, hasta, 2 AS numParada
FROM rutas
WHERE desde = @inicio
UNION ALL
SELECT r.desde, r.hasta, numParada + 1
FROM rutas r
INNER JOIN viaje v
ON v.hasta = r.desde
)
SELECT @inicio AS parada, 1 AS numParada
UNION
SELECT hasta, numParada
FROM viaje;

***************************************************************************************

"Caminar sobre el agua y desarrollar software a partir de unas
especificaciones es fácil, si ambas están congeladas."
Edward V. Berard, ingeniero informático


"Nelson" wrote in message
news:%
Quitando los detalles tengo una tabla con algo como esto:

Rutas
-
parada1, parada2

A B
A C
B D
D E

Si me piden sacar la "ruta" desde A hasta E, debe sacarme un varchar
con 'A-B-D-E'.

Se que lo puedo hacer con un cursor recorriendo los registros pero me
han dicho que no se aconseja.

Hay manera de hacerlo con un select ? alguna orientacion que me
puedan dar pues no lo entiendo

Grax

ss2008
















Respuesta Responder a este mensaje
#9 Nelson
27/10/2009 - 21:33 | Informe spam
Antes de responderte había probado el script del primer mensaje tuyo
agregando este registro:
insert into @Conexiones values ('I','E')
y se me iba a un loop infinito

Pero como bien indicaste en este mensaje agregando la condición "where C.A
<> @destino" queda perfecto.

Muchas gracias Carlos. Excelente ayuda!

"Carlos M. Calvelo" wrote in message
news:
Hola Nelson,

Puedes añadir también una condición en la segunda
consulta del with, como indico abajo, para evitar seguir
haciendo joins innecesarios cuando ya se ha llegado
al destino.


On 27 okt, 18:34, "Carlos M. Calvelo" wrote:

set nocount on

declare @Conexiones table(A char(1), B char(1))
insert into @Conexiones values ('A','B')
insert into @Conexiones values ('A','C')
insert into @Conexiones values ('A','D')
insert into @Conexiones values ('B','E')
insert into @Conexiones values ('C','F')
insert into @Conexiones values ('C','G')
insert into @Conexiones values ('E','G')
insert into @Conexiones values ('F','E')
insert into @Conexiones values ('F','H')
insert into @Conexiones values ('G','I')
insert into @Conexiones values ('H','I')

declare @origen char(1), @destino char(1)
set @origen = 'A'
set @destino = 'I'

;
with Viajes as
(
select
cast(A+'-'+B as varchar(max)) Ruta,
B PuntoFinal,
2 #Puntos
from @Conexiones
where A = @origen
union all
select
cast(V.ruta+'-'+C.B as varchar(max)) Ruta,
C.B PuntoFinal,
#Puntos+1 #Puntos
from Viajes V join @Conexiones C on V.PuntoFinal = C.A



where C.A <> @destino

)
select Ruta, #Puntos
from Viajes
where PuntoFinal = @destino




Saludos,
Carlos
Respuesta Responder a este mensaje
#10 Carlos M. Calvelo
27/10/2009 - 22:27 | Informe spam
Hola Nelson,

On 27 okt, 21:33, "Nelson" wrote:
Antes de responderte había probado el script del primer mensaje tuyo
agregando este registro:
insert into @Conexiones values ('I','E')
y se me iba a un loop infinito

Pero como bien indicaste en este mensaje agregando la condición "where C.A
<> @destino" queda perfecto.

Muchas gracias Carlos. Excelente ayuda!




Cuidado! Con ese registro estás creando un ciclo: (E->G->I->E)
Ya te había dicho que tuvieras cuidado con eso. Aunque puse un
emoticón era un aviso en serio. Mi intención con la consulta
era recorrer un grafo direcional acíclico!

En este caso (origen A, destino I y con el registro que tu has
agregado) el bucle (el loop) para porque reconoce el destino
(que está en el ciclo!) y no sigue buscando. Pero prueba por
ejemplo con origen A y destino F y verás que no vuelve. Buscando
posibles rutas, la búsquedas que se meten en el ciclo no llegarán
ni al destino ni a un punto final.

En una situación real habría que poner una restricción sobre
esa tabla para evitar que se formen ciclos (si lo que se quiere
representar es un grafo acíclico). Y si sí tienen que ser posibles
los ciclos habrá que revisar la consulta para reconocerlos.

Saludos,
Carlos
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida