¿La mejor manera de SQL Server para calcular la fecha entre la fila actual y la siguiente?
-
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.
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.