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:

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


Respuesta Responder a este mensaje
#2 Tumba
06/09/2005 - 15:06 | Informe spam
Impresionante!!!, muchas gracias un ejemplo de hacer las cosas faciles!!! :)

"Alejandro Mesa" escribió:

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:

> 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
>
>
Respuesta Responder a este mensaje
#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ó:

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:

> Hola, lamentablemente festeje antes de tiempo :o(
> probe el ejemplo con los datos que habia pasado.
> El problema esta que los IdFecha no son correlativos con los rangos de
> fecha, y la consulta esta tomando los rangos que empiezan o terminan dentro
> de uno y elige el menor pero no esta tomando en cuenta los rangos menores que
> se vienen anidando Por Ejemplo: (pongo los rangos con rayitas para no poner
> las fechas)
>
> 1 - Elige 1
> 2 -- Elige 1
> 3 - Elige 1
> 4 -- Elige 3 (Tendria que elegir 1)
> 5 --Elige 4 (Tendria que elegir 1)
> 6 - Elige 1
> 7 - Elige 5 (Tendria
> que elegir 1)
> 8 Elige
> 7 (Tendria que elegir 1)
>
> Tendria de Devolver
>
> fin rango 8)
>
> Pongo un ejemplo con datos reales.
>
> create table t1(
> idServicioHistorico int not null identity primary key,
> FechaAlta datetime not null,
> FechaBaja datetime null,
> idAgente int not null
> )
> 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 view v1
> as
> select isnull(
> (
> select
> min(b.idServicioHistorico)
> from
> t1 as b
> where b.idAgente = a.idAgente
> and
> (
> a.FechaAlta between b.FechaAlta and
> ISNULL(b.FechaBaja,GETDATE())
> or
> a.FechaBaja between b.FechaAlta and
> ISNULL(b.FechaBaja,GETDATE())
> )
>
> ), a.idServicioHistorico) as Rango,
> idServicioHistorico,
> FechaAlta,
> FechaBaja,
> idAgente
> from t1 as a
> go
>
> select rango,
> min(fechaalta) as fecha_alta,
> max(fechabaja) as fecha_baja,
> min(idAgente) as idAgente
> from v1
> group by rango
> order by rango
> go
>
>
> drop view v1
> drop table t1
> go
>
>
>
> FechaAlta FechaBaja Agente Rango * (rango puesto
> secuencialmente)
> 08/03/1977 28/11/1977 31068 1
> 01/03/1978 16/09/1982 31068 2
> 01/03/1983 07/06/1983 31068 3
> 27/02/1984 20/02/1989 31068 4
> 21/02/1989 04/05/1999 31068 5
> 05/05/1999 10/12/1999 31068 6
> 31/12/1999 GETDATE() 31068 7
>
>
>
> Muchas Gracias por cualquier sugerencia
>
>
>
> "Alejandro Mesa" escribió:
>
> > 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)
Respuesta Responder a este mensaje
#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:

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ó:

> 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:
>
> > Hola, lamentablemente festeje antes de tiempo :o(
> > probe el ejemplo con los datos que habia pasado.
> > El problema esta que los IdFecha no son correlativos con los rangos de
> > fecha, y la consulta esta tomando los rangos que empiezan o terminan dentro
> > de uno y elige el menor pero no esta tomando en cuenta los rangos menores que
> > se vienen anidando Por Ejemplo: (pongo los rangos con rayitas para no poner
> > las fechas)
> >
> > 1 - Elige 1
> > 2 -- Elige 1
> > 3 - Elige 1
> > 4 -- Elige 3 (Tendria que elegir 1)
> > 5 --Elige 4 (Tendria que elegir 1)
> > 6 - Elige 1
> > 7 - Elige 5 (Tendria
> > que elegir 1)
> > 8 Elige
> > 7 (Tendria que elegir 1)
> >
> > Tendria de Devolver
> >
> > fin rango 8)
> >
> > Pongo un ejemplo con datos reales.
> >
> > create table t1(
> > idServicioHistorico int not null identity primary key,
> > FechaAlta datetime not null,
> > FechaBaja datetime null,
> > idAgente int not null
> > )
> > 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 view v1
> > as
> > select isnull(
> > (
> > select
> > min(b.idServicioHistorico)
> > from
> > t1 as b
> > where b.idAgente = a.idAgente
Respuesta Responder a este mensaje
#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:

Hola, lamentablemente festeje antes de tiempo :o(
probe el ejemplo con los datos que habia pasado.
El problema esta que los IdFecha no son correlativos con los rangos de
fecha, y la consulta esta tomando los rangos que empiezan o terminan dentro
de uno y elige el menor pero no esta tomando en cuenta los rangos menores que
se vienen anidando Por Ejemplo: (pongo los rangos con rayitas para no poner
las fechas)

1 - Elige 1
2 -- Elige 1
3 - Elige 1
4 -- Elige 3 (Tendria que elegir 1)
5 --Elige 4 (Tendria que elegir 1)
6 - Elige 1
7 - Elige 5 (Tendria
que elegir 1)
8 Elige
7 (Tendria que elegir 1)

Tendria de Devolver

fin rango 8)

Pongo un ejemplo con datos reales.

create table t1(
idServicioHistorico int not null identity primary key,
FechaAlta datetime not null,
FechaBaja datetime null,
idAgente int not null
)
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 view v1
as
select isnull(
(
select
min(b.idServicioHistorico)
from
t1 as b
where b.idAgente = a.idAgente
and
(
a.FechaAlta between b.FechaAlta and
ISNULL(b.FechaBaja,GETDATE())
or
a.FechaBaja between b.FechaAlta and
ISNULL(b.FechaBaja,GETDATE())
)

), a.idServicioHistorico) as Rango,
idServicioHistorico,
FechaAlta,
FechaBaja,
idAgente
from t1 as a
go

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


drop view v1
drop table t1
go



FechaAlta FechaBaja Agente Rango * (rango puesto
secuencialmente)
08/03/1977 28/11/1977 31068 1
01/03/1978 16/09/1982 31068 2
01/03/1983 07/06/1983 31068 3
27/02/1984 20/02/1989 31068 4
21/02/1989 04/05/1999 31068 5
05/05/1999 10/12/1999 31068 6
31/12/1999 GETDATE() 31068 7



Muchas Gracias por cualquier sugerencia



"Alejandro Mesa" escribió:

> 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:
>
> > 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
> >
> >
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida