SQL Server miglior modo per calcolare il datediff tra riga e riga successiva?
-
09-06-2019 - |
Domanda
Io ho avuto la seguente ruvida struttura:
Object -> Object Revisions -> Data
I Dati possono essere condivisi tra più Oggetti.
Quello che sto cercando di fare è pulire vecchio Oggetto di revisione.Voglio mantenere la prima, attiva, e una diffusione di revisioni in modo che l'ultima sostituzione per un periodo di tempo viene mantenuto.I Dati potrebbero essere cambiato molto nel corso di 2 giorni e poi lasciato per mesi, quindi voglio mantenere l'ultima revisione prima che il cambiamento è iniziato e la fine di cambiare di nuovo insieme.
Attualmente sto usando un cursore e temp tabella per contenere l'Id e la data tra le modifiche in modo che posso selezionare la frutta a basso impiccagione per sbarazzarsi di.Questo comporta l'uso di @LastID, @LastDate, aggiornamenti e inserimenti per la tabella temporanea, ecc...
C'è una semplificazione/modo migliore per calcolare la data di differenza tra la riga e la riga successiva nel mio primo set di risultati senza l'utilizzo di un cursore e la tabella temporanea?
Io sono su sql server 2000, ma sarebbe interessato a tutte le nuove caratteristiche del 2005, del 2008, che potrebbe aiutare con questo.
Soluzione
Se la colonna identity è sequenziale è possibile utilizzare questo approccio:
SELECT curr.*, DATEDIFF(MINUTE, prev.EventDateTime,curr.EventDateTime) Duration FROM DWLog curr join DWLog prev on prev.EventID = curr.EventID - 1
Altri suggerimenti
Qui è un esempio di SQL.Se si dispone di una colonna di Identità, è possibile utilizzare questo al posto di "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)
Ho potuto rimuovere "prev", ma lì se c'è bisogno di Id per l'eliminazione.
Hrmm, sfida interessante.Penso che si può fare senza un self-join se si utilizza il nuovo-per-2005 funzionalità pivot.
Ecco quello che ho ottenuto finora, ho voluto dare a questo un po ' più di tempo prima di accettare una risposta.
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
Sto cercando di estendere questo modo che è possibile mantenere la massima così molte revisioni, e potare fuori per i più vecchi, pur mantenendo il primo, l'ultimo e attivo.Dovrebbe essere abbastanza semplice attraverso la selezione di top e clausole order by, um...e a tirare in ActiveDate nella tabella temporanea.
Ho ottenuto Pietro esempio per lavoro, ma ha preso e modificato in una subselect.Ho pasticciato con entrambi e sql traccia mostra il subselect fare a meno di letture.Ma non funziona e mi votano lui fino a quando ho il mio rep abbastanza alta.