¿La mejor manera de SQL Server para calcular la fecha entre la fila actual y la siguiente?

StackOverflow https://stackoverflow.com/questions/52430

  •  09-06-2019
  •  | 
  •  

Pregunta

Tengo la siguiente estructura aproximada:

Object -> Object Revisions -> Data

Los Datos se pueden compartir entre varios Objetos.

Lo que intento hacer es limpiar las revisiones de objetos antiguas.Quiero mantener la primera revisión activa y una serie de revisiones para mantener el último cambio durante un período de tiempo.Los datos pueden cambiar mucho en el transcurso de 2 días y luego dejarse solos durante meses, por lo que quiero conservar la última revisión antes de que comenzaran los cambios y el cambio final del nuevo conjunto.

Actualmente estoy usando un cursor y una tabla temporal para contener los ID y la fecha entre cambios, de modo que pueda seleccionar la fruta madura de la que deshacerme.Esto significa usar @LastID, @LastDate, actualizaciones e inserciones en la tabla temporal, etc.

¿Existe una manera mejor o más fácil de calcular la diferencia de fecha entre la fila actual y la siguiente fila en mi conjunto de resultados inicial sin usar un cursor y una tabla temporal?

Estoy en SQL Server 2000, pero estaría interesado en cualquier característica nueva de 2005, 2008 que también pueda ayudar con esto.

¿Fue útil?

Solución

Si la columna de identidad es secuencial, puede utilizar este enfoque:

SELECT curr.*, DATEDIFF(MINUTE, prev.EventDateTime,curr.EventDateTime) Duration FROM DWLog curr join DWLog prev on prev.EventID = curr.EventID - 1

Otros consejos

Aquí hay un ejemplo de SQL.Si tiene una columna de Identidad, puede usarla en lugar de "ActivityDate".

SELECT DATEDIFF(HOUR, prev.ActivityDate, curr.ActivityDate)
  FROM MyTable curr
  JOIN MyTable prev
    ON prev.ObjectID = curr.ObjectID
  WHERE prev.ActivityDate =
     (SELECT MAX(maxtbl.ActivityDate)
        FROM MyTable maxtbl
        WHERE maxtbl.ObjectID = curr.ObjectID
          AND maxtbl.ActivityDate < curr.ActivityDate)

Podría eliminar "anterior", pero tenerlo allí suponiendo que necesite sus ID para eliminarlo.

Hmmm, desafío interesante.Creo que puede hacerlo sin una autounión si utiliza la funcionalidad pivote nueva en 2005.

Esto es lo que tengo hasta ahora. Quería darle un poco más de tiempo antes de aceptar una respuesta.

DECLARE @IDs TABLE 
(
  ID int , 
  DateBetween int
)

DECLARE @OID int
SET @OID = 6150

-- Grab the revisions, calc the datediff, and insert into temp table var.

INSERT @IDs
SELECT ID, 
       DATEDIFF(dd, 
                (SELECT MAX(ActiveDate) 
                 FROM ObjectRevisionHistory 
                 WHERE ObjectID=@OID AND 
                       ActiveDate < ORH.ActiveDate), ActiveDate) 
FROM ObjectRevisionHistory ORH 
WHERE ObjectID=@OID


-- Hard set DateBetween for special case revisions to always keep

 UPDATE @IDs SET DateBetween = 1000 WHERE ID=(SELECT MIN(ID) FROM @IDs)

 UPDATE @IDs SET DateBetween = 1000 WHERE ID=(SELECT MAX(ID) FROM @IDs)

 UPDATE @IDs SET DateBetween = 1000 
 WHERE ID=(SELECT ID 
           FROM ObjectRevisionHistory 
           WHERE ObjectID=@OID AND Active=1)


-- Select out IDs for however I need them

 SELECT * FROM @IDs
 SELECT * FROM @IDs WHERE DateBetween < 2
 SELECT * FROM @IDs WHERE DateBetween > 2

Estoy buscando extender esto para poder mantener al máximo tantas revisiones y eliminar las más antiguas mientras mantengo la primera, la última y activa.Debería ser bastante fácil seleccionando la parte superior y ordenando por cláusulas, um...y agregando ActiveDate a la tabla temporal.

Conseguí que el ejemplo de Peter funcionara, pero lo tomé y lo modifiqué en una subselección.Jugué con ambos y el seguimiento de SQL muestra que la subselección realiza menos lecturas.Pero funciona y votaré por él cuando tenga mi reputación lo suficientemente alta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top