SQL Server - Se puede hacer con un select ?
Asked By Nelson
27-Oct-09 12:20 AM
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
INNER JOIN
(1)
UNION ALL
(1)
Declare
(1)
Nocount
(1)
Varchar
(1)
PuntoFinal
(1)
FAsquedas
(1)
EDgenes
(1)
Carlos Sacristan replied to Nelson
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;
***************************************************************************************
--
-----------------------------
especificaciones es f?cil, si ambas est?n congeladas."
Edward V. Berard, ingeniero inform?tico
Nelson replied to Carlos Sacristan
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 replied to Nelson
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.
--
-----------------------------
especificaciones es f?cil, si ambas est?n congeladas."
Edward V. Berard, ingeniero inform?tico
Nelson replied to Carlos Sacristan
Exacto, debe ser una t?cnica de ensayo y error, recursivo.
Carlos Sacristan replied to Nelson
???? No te entiendo...
--
-----------------------------
especificaciones es f?cil, si ambas est?n congeladas."
Edward V. Berard, ingeniero inform?tico
Carlos M. Calvelo replied to Nelson

Hola Nelson,
dar
Aqu=ED abajo te dejo un ejemplo. Si quieres hacer pruebas
con =E9l prueba tambi=E9n otros or=EDgenes y destinos.
Quiz=E1s 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 =3D 'A'
set @destino =3D 'I'
;
with Viajes as
(
select
cast(A+'-'+B as varchar(max)) Ruta,
B PuntoFinal,
2 #Puntos
from @Conexiones
where A =3D @origen
union all
select
cast(V.ruta+'-'+C.B as varchar(max)) Ruta,
C.B PuntoFinal,
from Viajes V join @Conexiones C on V.PuntoFinal =3D C.A
)
select Ruta, #Puntos
from Viajes
where PuntoFinal =3D @destino
Saludos,
Carlos
Carlos M. Calvelo replied to Carlos M. Calvelo
Hola Nelson,
Puedes a=F1adir tambi=E9n una condici=F3n en la segunda
consulta del with, como indico abajo, para evitar seguir
haciendo joins innecesarios cuando ya se ha llegado
al destino.
where C.A <> @destino
Saludos,
Carlos
Nelson replied to Carlos Sacristan
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".
Nelson replied to Carlos M. Calvelo
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
Muchas gracias Carlos. Excelente ayuda!
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.
where C.A <> @destino
Saludos,
Carlos
Carlos M. Calvelo replied to Nelson
Hola Nelson,
C.A
Cuidado! Con ese registro est=E1s creando un ciclo: (E->G->I->E)
Ya te hab=EDa dicho que tuvieras cuidado con eso. Aunque puse un
emotic=F3n era un aviso en serio. Mi intenci=F3n con la consulta
era recorrer un grafo direcional ac=EDclico!
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=E1 en el ciclo!) y no sigue buscando. Pero prueba por
ejemplo con origen A y destino F y ver=E1s que no vuelve. Buscando
posibles rutas, la b=FAsquedas que se meten en el ciclo no llegar=E1n
ni al destino ni a un punto final.
En una situaci=F3n real habr=EDa que poner una restricci=F3n sobre
esa tabla para evitar que se formen ciclos (si lo que se quiere
representar es un grafo ac=EDclico). Y si s=ED tienen que ser posibles
los ciclos habr=E1 que revisar la consulta para reconocerlos.
Saludos,
Carlos
Carlos M. Calvelo replied to Nelson
Hola Nelson,
Aqu=ED te dejo otra version que reconoce ciclos. Solo he a=F1adido
el charindex(...) en el where de la segunda consulta.
Esa condici=F3n se encarga de parar la noria si nos encontramos con
un punto que ya est=E1 en la Ruta.
;
with Viajes as
(
select
cast(A+'-'+B as varchar(max)) Ruta,
B PuntoFinal,
2 #Puntos
from @Conexiones
where A =3D @origen
union all
select
cast(V.ruta+'-'+C.B as varchar(max)) Ruta,
C.B PuntoFinal,
from Viajes V join @Conexiones C on V.PuntoFinal =3D C.A
where C.A <> @destino and charindex('-'+C.B+'-','-'+Ruta+'-')=3D0
)
select Ruta, #Puntos
from Viajes
where PuntoFinal =3D @destino
Saludos,
Carlos
Nelson replied to Carlos M. Calvelo
Ya entiendo, aunque no te niego que me ha costado mucho esfuerzo entender la
lógica de los CTE's recursivos, pero ahí le vamos :)
Nuevamente muchas gracias por la ayuda, Carlos, este tema me ha servido para
aprender, de hecho hasta replantearme soluciones de otros problemas
similares con que uno se topa diariamente.
Saludos
and load with sample data Create Table #ORDERS (O_ID int) Insert #ORDERS (O_ID) Select 1 Union All Select 2 Union All Select 3 Union All Select 4 Union All Select 5 Union All Select 6 Create Table #ORDER_DETAILS (ORDER_ID int, PRODUCT_ID int, ORDER_SPECIFIC_PRODUCT_PRICE int) Insert #ORDER_DETAILS (ORDER_ID PRODUCT_ID, ORDER_SPECIFIC_PRODUCT_PRICE) Select 1, 1, 20 Union All Select 1, 2, 30 Union All Select 2, 1, 20 Union All Select 3, 1, 20 Union All Select 3, 2, 30 Union All Select 3
CREATE TABLE (1) ALTER TABLE (1) PRIMARY KEY (1) DROP TABLE (1) NOT NULL (1) Varchar (1) Declare (1) CREATE TABLE #SectionCrossTally ( Event_ID VARCHAR(12), Cross_ID VARCHAR(12), PRIMARY KEY (Event_ID, Cross_ID) ); INSERT #SectionCrossTally SELECT 'ENG 101', 'HUM 101' UNION SELECT 'HUM 101', 'ENG 101' UNION SELECT 'ENG 101', 'ART 101 UNION SELECT 'ART 101', 'ENG 101'; SELECT Events = REPLACE(REPLACE( ( SELECT e AS [data()] FROM ( SELECT DISTINCT e = REPLACE(Event_ID, ' ', '~') FROM #SectionCrossTally UNION SELECT DISTINCT REPLACE(Cross_ID, ' ', '~') FROM #SectionCrossTally ) AS x FOR XML PATH ('') ), ' ', ' / '), '~', ' '); DROP TABLE #SectionCrossTally; On
int NOT NULL ) GO INSERT INTO dbo.Table1 SELECT 1, 0, 1, 1, 0, 1 UNION ALL SELECT 2, 0, 1, 1, 1, 0 UNION ALL SELECT 3, 1, 0, 0, 1, 0 UNION ALL SELECT 4, 0, 1, 1, 1, 1 UNION ALL SELECT 5, 1, 0, 0, 0, 0 GO SELECT id, 1 AS seq, c1 AS c INTO dbo.Table2 FROM dbo.Table1 WHERE c1 = 1 UNION ALL SELECT id, 2, c2 FROM dbo.Table1 WHERE c2 = 1 UNION ALL SELECT id, 3, c3 FROM dbo.Table1 WHERE c3 = 1 UNION ALL SELECT id, 4, c4 FROM dbo.Table1 WHERE c4 = 1 UNION ALL SELECT id, 5, c5 FROM dbo.Table1 WHERE c5 = 1 GO ALTER TABLE dbo
INNER JOIN vs. WHERE for performance issue SQL Server Hi Expert, i have one interesting question between inner join with (w / o) statment. i have do few experiment between JOIN with WHERE, i found that the response time give me some different. declare @table1 table ( id int identity , value varchar(10) ) declare @table2 table ( tblID int ) insert @table1 select 'A' union all select 'B' union all select
0) AS FloorArea 'not summing SUM(pa.LIVING) AS FloorArea 'not summing either FROM pa INNER JOIN ON pa.ID = l.ID WHERE pa.ID = 1 GROUP BY l.ID, pa.ID LIVING SQL Server Programming Discussions SQL Server 2005 (1) CREATE TABLE (1) PRIMARY KEY (1) INNER JOIN (1) Declare (1) Varchar (1) Dude, We cannot guess at your DDL. Post some DDL. You have to remove GROUP BY clause: SELECT pa.ID, l.ID, SUM(pa.LIVING) AS FloorArea FROM pa INNER JOIN l ON pa.ID = l.ID WHERE pa.ID = 1 GROUP BY l.ID, pa