Query Recursivo

12/10/2008 - 06:39 por renemoreno | Informe spam
Hola a todos, a ver si alguien me puede ayudar con esto que ya me
tiene mareado.

Tengo dos campos con numero de codigo [DOCTO] y [DOCTOCOMP], un codigo
en DOCTO tiene un DOCTOCOMP, este codigo de DOCTOCOMP taambien existe
en el campo DOCTO y tambien tiene un DOCTOCOMP, esto se repite hasta
que DOCTO y DOCTOCOMP son iguales, ahi termina la secuencia. Por
ejemplo:

DOCTO - DOCTOCOMP
11111 - 22222
22222 - 33333
33333 - 44444
44444 - 44444

Estoy tratando de obtener el DOCTO incial y el DOCTOCOMP final, para
el ejemplo anterior seria 11111 - 44444.

Espero haber sido claro y de antemano agradezco cualquier ayuda que me
puedan dar.

Saludos
Rene Moreno

Preguntas similare

Leer las respuestas

#6 Alfredo Novoa
12/10/2008 - 20:58 | Informe spam
Hola Leonardo,

El Sun, 12 Oct 2008 10:44:48 -0430, Leonardo Azpurua escribió:

En los BOL del 2000 aparecen sólo dos instancias de "transitive closure",
ambas relacionadas con otra cosa, y ni un resultado para CTE.



Es que las CTE como dice Pedro las incluyeron en el 2005.

Busqué en
Google, pero me aburrí antes de encontrar nada util (aparece un articulo de
SQL Journal, o como quiera que se llame, pero es solo para suscriptores, lo
único que se puede acceder es el código, que es un poco coñazo).



Pues que más quieres :-). Si miras el siguiente enlace también hay otro
ejemplo.

http://www.eggheadcafe.com/forumarc...683455.asp

Puedes sugerir algún vínculo que explique -como para que lo entienda un
desarrollador de aplicaciones de negocios- de que van las CTE?



Si buscas CTE + "SQL Server" te saldrán cerca de 60.000 enlaces. También
puedes buscar "recursive queries".

Y como me has pillado de buen humor ya te lo doy todo hecho :-)

with T as
(
select DOCTO, DOCTOCOMP from LaTabla
union all
select e.DOCTO, t.DOCTOCOMP
from LaTabla e, T
where e.DOCTOCOMP = t.DOCTO
)

select docto,doctocomp from t where docto not in (select doctocomp from t)
and doctocomp not in (select docto from t)



Saludos
Alfredo
Respuesta Responder a este mensaje
#7 Alfredo Novoa
12/10/2008 - 23:38 | Informe spam
Bueno, todo hecho no estaba. Faltaba eliminar las filas donde los dos
campos son iguales, que no hacen más que molestar.

Entonces quedaría así:

with x as (select * from latabla where docto<>doctocomp), y as (select
docto, doctocomp from x union all select x.docto, y.doctocomp from x, y
where x.doctocomp = y.docto) select docto, doctocomp from y where docto not
in (select doctocomp from y) and doctocomp not in (select docto from y)

Aunque esas filas sería mejor borrarlas de la tabla.


Saludos
Respuesta Responder a este mensaje
#8 Leonardo Azpurua
13/10/2008 - 00:04 | Informe spam
"Alfredo Novoa" escribió en el mensaje
news:1j477bq6ra1i9$.1hinqvqaczqao$
Bueno, todo hecho no estaba. Faltaba eliminar las filas donde los dos
campos son iguales, que no hacen más que molestar.

Entonces quedaría así:

with x as (select * from latabla where docto<>doctocomp), y as (select
docto, doctocomp from x union all select x.docto, y.doctocomp from x, y
where x.doctocomp = y.docto) select docto, doctocomp from y where docto
not
in (select doctocomp from y) and doctocomp not in (select docto from y)

Aunque esas filas sería mejor borrarlas de la tabla.



Yo igual me quedé sin entender nada :)

De todas maneras, si algún día la necesidad aparece, ya al menos sé por
donde buscar.


Salud!
Respuesta Responder a este mensaje
#9 Alfredo Novoa
13/10/2008 - 01:33 | Informe spam
El Sun, 12 Oct 2008 17:34:11 -0430, Leonardo Azpurua escribió:

with x as (select * from latabla where docto<>doctocomp), y as (select
docto, doctocomp from x union all select x.docto, y.doctocomp from x, y
where x.doctocomp = y.docto) select docto, doctocomp from y where docto
not
in (select doctocomp from y) and doctocomp not in (select docto from y)

Aunque esas filas sería mejor borrarlas de la tabla.



Yo igual me quedé sin entender nada :)



Es muy fácil.

Las CTE son simplemente expresiones "with".

with x as (select * from latabla where docto<>doctocomp)

Con esto simplemente creamos una variable temporal llamada x que es igual
al resultado de la consulta entre parentesis.

Podemos crear más variables de esas poniendo comas

with x as (...), y as (...), z as ...

Y podemos usar esas variables en las siguientes variables que definamos e
incluso en la misma variable que estamos definiendo, y esto es lo que
permite las consultas recursivas.

y as
(
select docto, doctocomp from x
union all
select x.docto, y.doctocomp from x, y
where x.doctocomp = y.docto
)

Esta subexpresión es la que calcula el cierre transitivo que nos daría este
resultado:

DOCTO - DOCTOCOMP
11111 - 22222
11111 - 33333
11111 - 44444
22222 - 33333
22222 - 44444
33333 - 44444

Así explicado para andar por casa, el cierre transitivo es simplemente una
lista de los elementos asociados por una relación transitiva. Relación
transitiva quiere decir que si A está relacionado con B y B está
relacionado con C entonces A está relacionado con C.

O también se podría representar como una lista de los nodos conectados
directa o indirectamente de un grafo dirigido acíclico. Todo esto viene en
cualquier introducción a la matemática discreta como la de 1º de la
carrera.

Aquí explican como funcionan las consultas recursivas:

http://msdn.microsoft.com/en-us/lib...86243.aspx

La expresión de debajo del union all es la expresión recursiva, y la de
encima es el enganche.

Y la expresión del "where" simplemente sirve para eliminar los registros
intermedios que nos sobran.

Si un código aparece en la columna DOCTOCOMP entonces quiere decir que ese
código no es el inicio de un grafo, y si no aparece en DOCTO quiere decir
que no es el final de un grafo. Si quitamos todo lo que no son ni inicios
ni finales entonces nos quedan los inicios y los finales que es lo que
queremos :-)

Las filas donde los dos campos son iguales hay que eliminarlas por que
crean un ciclo y por lo tanto recursividad infinita. Aunque SQL Server solo
permite 100 niveles de recursividad, por lo menos tal y como lo tengo yo
configurado, y no se si se puede cambiar.

En resumen, que esta es una de las consultas recursivas más sencillitas que
pueda haber :-)

De todas maneras, si algún día la necesidad aparece, ya al menos sé por
donde buscar.



Las consultas recursivas son muy útiles para calcular escandallos y cosas
así, y las CTE son utilísimas para casi todo.


Saludos
Respuesta Responder a este mensaje
#10 Alfredo Novoa
13/10/2008 - 02:09 | Informe spam
On 13 oct, 01:33, Alfredo Novoa wrote:
El Sun, 12 Oct 2008 17:34:11 -0430, Leonardo Azpurua escribió:

Y la expresión del "where" simplemente sirve para eliminar los registros
intermedios que nos sobran.



Aquí me refiero a esta:

where docto not in (select doctocomp from y) and doctocomp not in
(select docto from y)

Si un código aparece en la columna DOCTOCOMP entonces quiere decir que ese
código no es el inicio de un grafo, y si no aparece en DOCTO
que no es el final de un grafo.



Esto último está al reves :(

Si un código aparece en DOCTO quiere decir que no es el final de un
grafo.


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