Como elimino el cursor

03/05/2006 - 21:27 por Horacio | Informe spam
Hola,

Primero les comento cual es la necesidad y como la resolvimos:

Tenemos que guardar los datos provenientes de distintas fuentes, estos datos
estan compuesto por clave (codTag), valor, fechaHora (momento en que se
genero el dato, no momento de insercion), y un valor de alarma que no nos
interesa.

La tabla tiene esta estructura:

CREATE TABLE [dbo].[ValoresHistoricos] (
[codTag] [smallint] NOT NULL ,
[valor] [float] NULL ,
[fechaHora] [datetime] NOT NULL ,
[alarma] [varchar] (6) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]

Se permite null en el campo valor porque tiene un significado especial para
la aplicacion.

El tema es que ahora necesitamos calcular datos como un promedio ponderado
en el tiempo. Por ej (olvidandonos del campo alarma):

codTag Valor FechaHora
1, 400, '1/1/1 00:00:00'
1, 200, '1/1/1 00:10:00'
1, 150, '1/1/1 00:30:00'
1, 100, '1/1/1 01:10:00'

el promedio ponderado en el tiempo para el codTag = 1 es:
400 * 10 minutos (son 10 minutos porque ese es el tiempo que duro en ese
valor)
+
200 * 20
+
150*40
000
Todo dividido 70 minutos
0 (este es el promedio ponderado en el tiempo para este codTag en ese
periodo)
La pregunta es:
¿Se puede obtener este resultado sin recurrir a un cursor como actualmente
se hace?

¿Es necesario proponer otra estructura en la tabla para mejorar el
rendimiento y evitar el cursor?

Hemos intentado hacer algo diferente precalculando valores mediante
triggers, pero se complica porque los datos pueden llegar a entrar
desordenados cronologicamente. Ejemplo, hoy pueden estar entrendo datos
actuales y datos de ayer para el mismo codTag.

Cualquier otra informacion que necesiten no duden en solicitarla.

Muchas gracias por su tiempo.

Saludos

Horacio
 

Leer las respuestas

#1 Alejandro Mesa
03/05/2006 - 21:43 | Informe spam
Trata,

select
a.codTag, sum(a.valor * datediff(minute, a.fechaHora, b.fechaHora)) /
datediff(minute, min(a.fechaHora), max(b.fechaHora))
from
[dbo].[ValoresHistoricos] as a
inner join
[dbo].[ValoresHistoricos] as b
on b.codTag = a.codTag
and b.fechaHora = (select min(c.fechaHora) from [dbo].[ValoresHistoricos]
as c where b.codTag = a.codTag and c.fechaHora > a.fechaHora)
group by
a.codTag
go


AMB

"Horacio" wrote:

Hola,

Primero les comento cual es la necesidad y como la resolvimos:

Tenemos que guardar los datos provenientes de distintas fuentes, estos datos
estan compuesto por clave (codTag), valor, fechaHora (momento en que se
genero el dato, no momento de insercion), y un valor de alarma que no nos
interesa.

La tabla tiene esta estructura:

CREATE TABLE [dbo].[ValoresHistoricos] (
[codTag] [smallint] NOT NULL ,
[valor] [float] NULL ,
[fechaHora] [datetime] NOT NULL ,
[alarma] [varchar] (6) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]

Se permite null en el campo valor porque tiene un significado especial para
la aplicacion.

El tema es que ahora necesitamos calcular datos como un promedio ponderado
en el tiempo. Por ej (olvidandonos del campo alarma):

codTag Valor FechaHora
1, 400, '1/1/1 00:00:00'
1, 200, '1/1/1 00:10:00'
1, 150, '1/1/1 00:30:00'
1, 100, '1/1/1 01:10:00'

el promedio ponderado en el tiempo para el codTag = 1 es:
400 * 10 minutos (son 10 minutos porque ese es el tiempo que duro en ese
valor)
+
200 * 20
+
150*40
000
Todo dividido 70 minutos
0 (este es el promedio ponderado en el tiempo para este codTag en ese
periodo)
La pregunta es:
¿Se puede obtener este resultado sin recurrir a un cursor como actualmente
se hace?

¿Es necesario proponer otra estructura en la tabla para mejorar el
rendimiento y evitar el cursor?

Hemos intentado hacer algo diferente precalculando valores mediante
triggers, pero se complica porque los datos pueden llegar a entrar
desordenados cronologicamente. Ejemplo, hoy pueden estar entrendo datos
actuales y datos de ayer para el mismo codTag.

Cualquier otra informacion que necesiten no duden en solicitarla.

Muchas gracias por su tiempo.

Saludos

Horacio


Preguntas similares