Código de funcion recursiva para calcular una fecha

06/08/2008 - 01:32 por Aldo | Informe spam
Amigos,

Tuve que calcular una fecha final a partir de una inicial
adicionandole una determinada cantidad de dias.

Pero esta fecha final no debia de considerar sabados, domingos ni
feriados, osea solo me debia considerar días laborables.

Después de indagar sobre funciones recursivas en SQL logre
desarrollarla.

Aquí les pego el codigo para que no se rompan la cabeza tanto como me
la rompí yo.

CREATE FUNCTION [dbo].[FU_AdicionarDias]
(
@FechaInicial Smalldatetime,
@DiasAdicionar Smallint
)
RETURNS Smalldatetime AS
BEGIN

DECLARE @NuevaFecha Smalldatetime
DECLARE @DiaPos Int
SET @NuevaFecha CONVERT(Smalldatetime,CONVERT(Varchar(10),@FechaInicial,111))
SET @DiaPos = 1

WHILE @DiaPos <= @DiasAdicionar
BEGIN
SELECT @NuevaFecha = dbo.FU_AdicionarDiasLaborables(@NuevaFecha)
SET @DiaPos = @DiaPos + 1
END

RETURN @NuevaFecha
END

CREATE FUNCTION [dbo].[FU_AdicionarDiasLaborables]
(
@Fecha Smalldatetime
)
RETURNS Smalldatetime AS
BEGIN


DECLARE @FechaNueva Smalldatetime
DECLARE @DiaFeriado Tinyint
SET @FechaNueva = DATEADD(DAY, 1, @Fecha)

A LA FUNCION

IF DATEPART(dw, @FechaNueva) = 7 OR DATEPART(dw, @FechaNueva) = 1
BEGIN
SET @FechaNueva = dbo.FU_AdicionarDiasLaborables(DATEADD(DAY, 1,
@Fecha))
END


ELSE
BEGIN
SELECT @DiaFeriado = COUNT(*)
FROM dbo.Feriado
WHERE TxEstFer='A'
AND NuAniFer = YEAR(@FechaNueva)
AND NuMesFer = MONTH(@FechaNueva)
AND NuDiaFer = DAY(@FechaNueva)

IF @DiaFeriado > 0
BEGIN
SET @FechaNueva = dbo.FU_AdicionarDiasLaborables(DATEADD(DAY, 1,
@Fecha))
END
END

RETURN @FechaNueva
END

Esta es mi tabla de feriado
CREATE TABLE [dbo].[Feriado](
[NuAniFer] [smallint] NOT NULL,
[NuMesFer] [tinyint] NOT NULL,
[NuDiaFer] [tinyint] NOT NULL,
[TxTipFer] [char](1) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
[TxDesFer] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AI NULL
CONSTRAINT [PK_Feriado] PRIMARY KEY CLUSTERED
(
[NuAniFer] ASC,
[NuMesFer] ASC,
[NuDiaFer] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]


Espero les sea de mucha ayuda

Aldo Teixeira Morón
Lima - Perú
 

Leer las respuestas

#1 Carlos
06/08/2008 - 02:31 | Informe spam
Con un solo ciclo While , sin recursividad, probablemente fuera mas
eficiente

Ejemplo (casi seudocodigo)

funcion AvanzaDias(datetime @fecha, int @Dias)
return datetime as
begin
set @fecha=@fechainicial
while @Dias>0
begin
set @fecha=dateadd(day,1,@fecha)
if not (dbo.FindeSemana(@fecha)=1 or dbo.Feriado(@fecha)=1)
@Dias=@Dias-1
end
return @fecha
end

Luego haces las funciones para devolver si es findesemana o feriado.

function FinDeSemana(datetime @fecha)
returns bit
as
return (case when day(@fecha)=1 or day(@fecha)=7 then 1 else 0 end)

function Feriado(datetime @fecha)
returns bit
as
return .. --la logica para saber si @fecha es feriada.



"Aldo" escribió en el mensaje
news:
Amigos,

Tuve que calcular una fecha final a partir de una inicial
adicionandole una determinada cantidad de dias.

Pero esta fecha final no debia de considerar sabados, domingos ni
feriados, osea solo me debia considerar días laborables.

Después de indagar sobre funciones recursivas en SQL logre
desarrollarla.

Aquí les pego el codigo para que no se rompan la cabeza tanto como me
la rompí yo.

CREATE FUNCTION [dbo].[FU_AdicionarDias]
(
@FechaInicial Smalldatetime,
@DiasAdicionar Smallint
)
RETURNS Smalldatetime AS
BEGIN

DECLARE @NuevaFecha Smalldatetime
DECLARE @DiaPos Int
SET @NuevaFecha CONVERT(Smalldatetime,CONVERT(Varchar(10),@FechaInicial,111))
SET @DiaPos = 1

WHILE @DiaPos <= @DiasAdicionar
BEGIN
SELECT @NuevaFecha = dbo.FU_AdicionarDiasLaborables(@NuevaFecha)
SET @DiaPos = @DiaPos + 1
END

RETURN @NuevaFecha
END

CREATE FUNCTION [dbo].[FU_AdicionarDiasLaborables]
(
@Fecha Smalldatetime
)
RETURNS Smalldatetime AS
BEGIN


DECLARE @FechaNueva Smalldatetime
DECLARE @DiaFeriado Tinyint
SET @FechaNueva = DATEADD(DAY, 1, @Fecha)

A LA FUNCION

IF DATEPART(dw, @FechaNueva) = 7 OR DATEPART(dw, @FechaNueva) = 1
BEGIN
SET @FechaNueva = dbo.FU_AdicionarDiasLaborables(DATEADD(DAY, 1,
@Fecha))
END


ELSE
BEGIN
SELECT @DiaFeriado = COUNT(*)
FROM dbo.Feriado
WHERE TxEstFer='A'
AND NuAniFer = YEAR(@FechaNueva)
AND NuMesFer = MONTH(@FechaNueva)
AND NuDiaFer = DAY(@FechaNueva)

IF @DiaFeriado > 0
BEGIN
SET @FechaNueva = dbo.FU_AdicionarDiasLaborables(DATEADD(DAY, 1,
@Fecha))
END
END

RETURN @FechaNueva
END

Esta es mi tabla de feriado
CREATE TABLE [dbo].[Feriado](
[NuAniFer] [smallint] NOT NULL,
[NuMesFer] [tinyint] NOT NULL,
[NuDiaFer] [tinyint] NOT NULL,
[TxTipFer] [char](1) COLLATE SQL_Latin1_General_CP1_CI_AI NULL,
[TxDesFer] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AI NULL
CONSTRAINT [PK_Feriado] PRIMARY KEY CLUSTERED
(
[NuAniFer] ASC,
[NuMesFer] ASC,
[NuDiaFer] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]


Espero les sea de mucha ayuda

Aldo Teixeira Morón
Lima - Perú

Preguntas similares