Función No Recursiva

05/09/2003 - 09:00 por Mauricio Sthandier R. | Informe spam
Me quedaron dando vueltas las exposiciones sobre 'Función Recursiva', y
pensaba si habría aún otra forma de resolver el tema. Lo siguiente funciona
igual para los datos de prueba que entrego que las 2 Funciones presentadas
(habría que ver si para cualquier tipo y condiciones de lista enlazada).
Si bien tiende a la ineficiencia (especialmente en tablas grandes) y es
iterativa, constituye otro acercamiento al tema.
Reproduzco DDL para copiar y pegar.

(Una consulta... con qué herramienta puedo verificar el rendimiento real de
esta función contra las otras 2 presentadas ? no espero que sea más rápida
pero quisiera saber cuanto más lenta es)


if exists (select * from dbo.sysobjects where id object_id(N'[tbl_prueba]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [tbl_prueba]
GO

CREATE TABLE [tbl_prueba] (
[id_tabla] [int] NULL ,
[cod_fila] [char] (4),
[id_padre] [int] NULL
) ON [PRIMARY]
GO

INSERT INTO tbl_prueba VALUES(10,'05',Null)
INSERT INTO tbl_prueba VALUES(20,'13',10)
INSERT INTO tbl_prueba VALUES(30,'04',20)
INSERT INTO tbl_prueba VALUES(15,'23',5)
INSERT INTO tbl_prueba VALUES(5,'222',1)
INSERT INTO tbl_prueba VALUES(25,'3455',15)
INSERT INTO tbl_prueba VALUES(50,'2435',25)
INSERT INTO tbl_prueba VALUES(9999,'555',50)
INSERT INTO tbl_prueba VALUES(1,'Alfa',Null)
INSERT INTO tbl_prueba VALUES(888,'ra',777)
INSERT INTO tbl_prueba VALUES(777,'Rive',666)
INSERT INTO tbl_prueba VALUES(666,'dier',555)
INSERT INTO tbl_prueba VALUES(555,'hand',444)
INSERT INTO tbl_prueba VALUES(444,'st',333)
INSERT INTO tbl_prueba VALUES(333,'icio',222)
INSERT INTO tbl_prueba VALUES(222,'maur',Null)
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[fn_ruta]')
and OBJECTPROPERTY(id, N'IsScalarFunction') = 1)
drop function [fn_ruta]
GO

CREATE FUNCTION dbo.fn_ruta(@ultimo_nodo varchar(10))
RETURNS varchar(512)
AS
BEGIN
DECLARE @sql varchar(512)
DECLARE @hijo varchar(10)
DECLARE @padre varchar(10)
DECLARE @retorno varchar(512)

SET @sql = @ultimo_nodo
SET @retorno = ''

SELECT
@hijo = CAST(id_tabla AS varchar(10)),
@padre = ISNULL('-' + CAST(id_padre AS varchar(10)), 'X'),
@retorno CASE
WHEN ISNULL(CHARINDEX(@hijo, @sql, LEN(@sql) - LEN(@hijo)), 0) = 0 OR
RIGHT(@sql, 1) = 'X' THEN
''
ELSE
RTRIM(cod_fila) + '.'
END
+ @retorno,
@sql @sql +
CASE
WHEN ISNULL(CHARINDEX(@hijo, @sql, LEN(@sql) - LEN(@hijo) + 1), 0) = 0 OR
RIGHT(@sql, 1) = 'X' THEN
''
ELSE
@padre
END
FROM tbl_prueba
WHERE id_tabla <= @ultimo_nodo
ORDER BY id_tabla DESC

RETURN LEFT(@retorno, LEN(@retorno) -1)

END
GO

SELECT dbo.fn_ruta(id_tabla), * FROM tbl_prueba ORDER BY id_padre
GO


Fear
is temporary.
Pride
is forever.
 

Leer las respuestas

#1 Mauricio Sthandier R.
06/09/2003 - 19:06 | Informe spam
Disculpen la otra versión era innecesariamente carretera y más complicada...
esta se comporta mucho mejor.

ALTER FUNCTION dbo.fn_ruta(@ultimo_nodo varchar(10))
RETURNS varchar(512)
AS
BEGIN
DECLARE @hijo varchar(10)
DECLARE @padre varchar(10)
DECLARE @retorno varchar(512)

SET @padre = @ultimo_nodo
SET @retorno = ''

SELECT
@hijo = CAST(id_tabla AS varchar(10)),
@retorno CASE
WHEN @padre = @hijo THEN
RTRIM(cod_fila) + '.'
ELSE
''
END
+ @retorno,
@padre = CASE
WHEN (@hijo = @padre) OR (@hijo = @ultimo_nodo)
THEN CAST(id_padre AS varchar(10))
ELSE @padre
END
FROM tbl_prueba
WHERE id_tabla <= @ultimo_nodo
ORDER BY id_tabla DESC

RETURN LEFT(@retorno, LEN(@retorno) -1)

END

Fear
is temporary.
Pride
is forever.



"Mauricio Sthandier R." <mauricio@@sthandier.net> escribió en el mensaje
news:
Me quedaron dando vueltas las exposiciones sobre 'Función Recursiva', y
pensaba si habría aún otra forma de resolver el tema. Lo siguiente


funciona
igual para los datos de prueba que entrego que las 2 Funciones presentadas
(habría que ver si para cualquier tipo y condiciones de lista enlazada).
Si bien tiende a la ineficiencia (especialmente en tablas grandes) y es
iterativa, constituye otro acercamiento al tema.
Reproduzco DDL para copiar y pegar.

(Una consulta... con qué herramienta puedo verificar el rendimiento real


de
esta función contra las otras 2 presentadas ? no espero que sea más rápida
pero quisiera saber cuanto más lenta es)


if exists (select * from dbo.sysobjects where id > object_id(N'[tbl_prueba]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [tbl_prueba]
GO

CREATE TABLE [tbl_prueba] (
[id_tabla] [int] NULL ,
[cod_fila] [char] (4),
[id_padre] [int] NULL
) ON [PRIMARY]
GO

INSERT INTO tbl_prueba VALUES(10,'05',Null)
INSERT INTO tbl_prueba VALUES(20,'13',10)
INSERT INTO tbl_prueba VALUES(30,'04',20)
INSERT INTO tbl_prueba VALUES(15,'23',5)
INSERT INTO tbl_prueba VALUES(5,'222',1)
INSERT INTO tbl_prueba VALUES(25,'3455',15)
INSERT INTO tbl_prueba VALUES(50,'2435',25)
INSERT INTO tbl_prueba VALUES(9999,'555',50)
INSERT INTO tbl_prueba VALUES(1,'Alfa',Null)
INSERT INTO tbl_prueba VALUES(888,'ra',777)
INSERT INTO tbl_prueba VALUES(777,'Rive',666)
INSERT INTO tbl_prueba VALUES(666,'dier',555)
INSERT INTO tbl_prueba VALUES(555,'hand',444)
INSERT INTO tbl_prueba VALUES(444,'st',333)
INSERT INTO tbl_prueba VALUES(333,'icio',222)
INSERT INTO tbl_prueba VALUES(222,'maur',Null)
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[fn_ruta]')
and OBJECTPROPERTY(id, N'IsScalarFunction') = 1)
drop function [fn_ruta]
GO

CREATE FUNCTION dbo.fn_ruta(@ultimo_nodo varchar(10))
RETURNS varchar(512)
AS
BEGIN
DECLARE @sql varchar(512)
DECLARE @hijo varchar(10)
DECLARE @padre varchar(10)
DECLARE @retorno varchar(512)

SET @sql = @ultimo_nodo
SET @retorno = ''

SELECT
@hijo = CAST(id_tabla AS varchar(10)),
@padre = ISNULL('-' + CAST(id_padre AS varchar(10)), 'X'),
@retorno > CASE
WHEN ISNULL(CHARINDEX(@hijo, @sql, LEN(@sql) - LEN(@hijo)), 0) = 0 OR
RIGHT(@sql, 1) = 'X' THEN
''
ELSE
RTRIM(cod_fila) + '.'
END
+ @retorno,
@sql > @sql +
CASE
WHEN ISNULL(CHARINDEX(@hijo, @sql, LEN(@sql) - LEN(@hijo) + 1), 0) = 0 OR
RIGHT(@sql, 1) = 'X' THEN
''
ELSE
@padre
END
FROM tbl_prueba
WHERE id_tabla <= @ultimo_nodo
ORDER BY id_tabla DESC

RETURN LEFT(@retorno, LEN(@retorno) -1)

END
GO

SELECT dbo.fn_ruta(id_tabla), * FROM tbl_prueba ORDER BY id_padre
GO


Fear
is temporary.
Pride
is forever.




Preguntas similares