Cursor vs Consultas

05/09/2005 - 20:25 por Tumba | Informe spam
Hola, buenas tardes, necesito ayuda por favor!!!, tengo un problema con un
Stored que usa cursores para hacer unos calculos que quiero reformular con
operaciones de conjunto.

Se trata de una Tabla te tiene rangos de fechas en los cuales un Docente a
trabajado

Ej:

IdFecha | FechaAlta | FechaBaja | Cargo | Escuela

1 | 10/10/1978 | 13/12/1978 | UEF | 1

2 | 10/11/1978 | 13/12/1978 | UEF | 2

3 | 10/10/1978 | 13/12/1988 | UEF | 3

4 | 10/10/1989 | 13/12/1989 | UEF | 1

5 | 10/10/1990 | 13/12/1991 | UEF | 1

6 | 10/12/1990 | 13/12/1992 | UEF | 3



el Stored usa cursores para tomar los rangos que un docente trabajo en un
cargo concatenando los rangos que estan superpuesto y eliminando los rangos
incluidos el resultado que devuelve el SP es el siguiente:



Rango | FechaAlta | FechaBaja | Cargo

1 | 10/10/1978 | 13/12/1988 | UEF

4 | 10/10/1989 | 13/12/1989 | UEF

5 | 10/10/1990 | 13/12/1992 | UEF



He logrado resolverlo con consultas anidadas sobre la tabla de fechas, pero
mi solucion no me convence ya que demora mas tiempo que el cursor y la logica
para entenderla es complicada.

Explico como lo resolvi para ver si a alguien se le ocurre una mejor manera.

Cree una Consulta que identifica los Incluidos (rangos que estan dentro de
otro)

Otra que identifica a los que InicianDentro (que no estan en Incluidos)

Otra que identifica a los que TerminanDentro.

Otra que Identifica a los que InicianRango (de los concatenados, son los que
Finalizan dentro que no estan en InicianDentro)

Otra que Identifica a los que FinalizanRango (de los concatenados, son los
que Inicializan dentro que no estan en FinalizanDentro)

Otra RangosJuntos que Junta los InicianRango con los Finalizan Rango

Otra consulta que obtiene los Rangos libres

y Una Final que hace la union de Rangos Libres y RangosJuntos.



Cabe aclarar que la tabla de fechas tiene 600.000 registros



Agradezco mucho cualquier aporte a la causa de antemano

Preguntas similare

Leer las respuestas

#1 Alejandro Mesa
05/09/2005 - 22:05 | Informe spam
Trata:

create table t1(
IdFecha int not null identity primary key,
FechaAlta datetime not null,
FechaBaja datetime not null,
Cargo char(3) not null,
Escuela int not null
)

insert into t1(FechaAlta, FechaBaja, Cargo, Escuela)
values('19781010', '19781213', 'UEF', 1)

insert into t1(FechaAlta, FechaBaja, Cargo, Escuela)
values('19781110', '19781213', 'UEF', 2)

insert into t1(FechaAlta, FechaBaja, Cargo, Escuela)
values('19781010', '19881213', 'UEF', 3)

insert into t1(FechaAlta, FechaBaja, Cargo, Escuela)
values('19891010', '19891213', 'UEF', 1)

insert into t1(FechaAlta, FechaBaja, Cargo, Escuela)
values('19901010', '19911213', 'UEF', 1)

insert into t1(FechaAlta, FechaBaja, Cargo, Escuela)
values('19901210', '19921213', 'UEF', 3)
go

create view v1
as
select
isnull(
(
select
min(b.IdFecha)
from
t1 as b
where
b.IdFecha < a.IdFecha
and
(
a.FechaAlta between b.FechaAlta and b.FechaBaja
or
a.FechaBaja between b.FechaAlta and b.FechaBaja
)
), a.IdFecha) as Rango,
IdFecha,
FechaAlta,
FechaBaja,
Cargo
from
t1 as a
go

select
rango,
min(fechaalta) as fecha_alta,
max(fechabaja) as fecha_baja,
min(cargo) as cargo
from
v1
group by
rango
order by
rango
go

drop view v1
go

drop table t1
go


AMB

"Tumba" wrote:

Mostrar la cita
#2 Tumba
06/09/2005 - 15:06 | Informe spam
Impresionante!!!, muchas gracias un ejemplo de hacer las cosas faciles!!! :)

"Alejandro Mesa" escribió:

Mostrar la cita
#3 Tumba
07/09/2005 - 02:10 | Informe spam
Grande maestro!!

Gracias por la ayuda brindada he aprendido mucho de las soluciones que me
has dado.

Te cuento que la funcion no resolvia algunos casos porque supone que los
IdServiciosHistoricos estan ordenados pero lo solucione (usando tus mismas
ideas) haciendo la funcion recursiva para encontrar el menor ServicioHistorico

pego el codigo por si a alguien le intereza

create function dbo.ufn_f1 (
@idServicioHistorico int
)
returns int
as
begin
declare @i int
declare @idServicioHistoricoMinimo as int
declare @idAgente int
declare @FechaAlta datetime
declare @FechaBaja datetime

set @i = @idServicioHistorico
select @idAgente = idAgente,
@FechaAlta = FechaAlta,
@FechaBaja = FechaBaja
from
dbo.tb_ServiciosHistoricos
where
idServicioHistorico = @i

if @idAgente is not null

select TOP 1 @idServicioHistoricoMinimo= (b.IdServicioHistorico)
from
dbo.tb_ServiciosHistoricos as b
where (b.IdAgente = @idAgente) AND
(
@FechaAlta between b.FechaAlta and b.FechaBaja
or
@FechaBaja between b.FechaAlta and b.FechaBaja
)
Order By b.FechaAlta Asc
if @idServicioHistoricoMinimo <> @idServicioHistorico
BEGIN
Set @i = dbo.ufn_f1(@idServicioHistoricoMinimo)
END
ELSE
BEGIN
Set @i= @idServicioHistoricoMinimo
END
return (@i)
END
go






"Alejandro Mesa" escribió:

Mostrar la cita
#4 Alejandro Mesa
07/09/2005 - 02:13 | Informe spam
Tumba,

Me alegra que hayaa podido adaptar la idea a tus necesidades. Ten presente
que si la funcion sobrepasa el nivel 32 de recursividad, sql server dara
error.

Deja ver si encuentro un poco de tiempo para dedicarle y ver si podemos
encontrar otra solucion.


AMB

"Tumba" wrote:

Mostrar la cita
#5 Alejandro Mesa
07/09/2005 - 02:14 | Informe spam
Tumba,

Por eso es importante la data de ejemplo y el resultado esperado. Eso nos
permite verficar la solucion propuesta. Ve si esta se adapta mejor a lo que
deseas.

use northwind
go

create table t1(
idServicioHistorico int not null identity primary key,
FechaAlta datetime not null,
FechaBaja datetime null,
idAgente int not null
)
go

set dateformat dmy

INSERT INTO T1(fechaAlta, fechaBaja,idAgente)
VALUES ('08/03/1977','28/11/1977',31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('01/03/1978','30/04/1982',31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('01/04/1982','16/09/1982',31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('01/03/1983', '07/06/1983',31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('27/02/1984','20/02/1989',31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('21/02/1989','22/02/1989',31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('22/02/1989', '28/03/1989', 31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('23/02/1989', '23/11/1994', 31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('28/03/1989', '19/04/1989', 31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('19/04/1989', '01/11/1990', 31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('01/01/1991', '09/03/1992', 31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('02/08/1993', '19/08/1993', 31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('02/08/1993', '01/01/1995', 31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('24/11/1994', '04/05/1999', 31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('05/05/1999', '10/12/1999', 31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('13/12/1999', '01/05/2003', 31068)
INSERT INTO T1(fechaAlta, fechaBaja, idAgente)
VALUES ('01/01/2001', NULL, 31068)
go

create function dbo.ufn_f1 (
@idServicioHistorico int
)
returns int
as
begin
declare @i int
declare @idAgente int
declare @FechaAlta datetime
declare @FechaBaja datetime

set @i = @idServicioHistorico

select
@idAgente = idAgente,
@FechaAlta = FechaAlta,
@FechaBaja = FechaBaja
from
dbo.t1
where
idServicioHistorico = @i

if @idAgente is not null
while exists(
select *
from dbo.t1
where
idServicioHistorico < @i
and
(
@FechaAlta between FechaAlta and FechaBaja
or
@FechaBaja between FechaAlta and FechaBaja
)
and idAgente = @idAgente
)
begin
select
@i = idServicioHistorico,
@FechaAlta = FechaAlta,
@FechaBaja = FechaBaja
from
dbo.t1
where
idServicioHistorico < @i
and
(
@FechaAlta between FechaAlta and FechaBaja
or
@FechaBaja between FechaAlta and FechaBaja
)
and idAgente = @idAgente
end

return (@i)
end
go

create view v1
as
select
dbo.ufn_f1(idServicioHistorico) as rank,
min(FechaAlta) as min_FechaAlta,
max(coalesce(FechaBaja, getdate())) as max_FechaBaja,
min(idAgente) as min_idAgente
from
dbo.t1
group by
dbo.ufn_f1(idServicioHistorico)
go

select
count(*) as rango,
a.min_FechaAlta as FechaAlta,
a.max_FechaBaja as FechaBaja,
a.min_idAgente as idAgente
from
v1 as a
inner join
v1 as b
on a.rank >= b.rank
group by
a.rank,
a.min_FechaAlta,
a.max_FechaBaja,
a.min_idAgente
order by
rango
go

drop view v1
go

drop function dbo.ufn_f1
go

drop table t1
go


AMB

"Tumba" wrote:

Mostrar la cita
Ads by Google
Search Busqueda sugerida