Beste Methode für SQL Server zur Berechnung des Datumsunterschieds zwischen der aktuellen Zeile und der nächsten Zeile?

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

  •  09-06-2019
  •  | 
  •  

Frage

Ich habe folgende grobe Struktur:

Object -> Object Revisions -> Data

Die Daten können von mehreren Objekten gemeinsam genutzt werden.

Ich versuche, alte Objektrevisionen zu bereinigen.Ich möchte die erste, aktive und eine Reihe von Revisionen beibehalten, sodass die letzte Änderung für einen bestimmten Zeitraum erhalten bleibt.Die Daten können im Laufe von zwei Tagen stark verändert werden und dann monatelang in Ruhe gelassen werden, daher möchte ich die letzte Revision behalten, bevor die Änderungen begannen und die Änderung des neuen Satzes endete.

Ich verwende derzeit einen Cursor und eine temporäre Tabelle, um die IDs und das Datum zwischen den Änderungen zu speichern, damit ich die niedrig hängenden Früchte auswählen kann, die ich entfernen möchte.Dies bedeutet die Verwendung von @LastID, @LastDate, Aktualisierungen und Einfügungen in die temporäre Tabelle usw.

Gibt es eine einfachere/bessere Möglichkeit, den Datumsunterschied zwischen der aktuellen Zeile und der nächsten Zeile in meiner ursprünglichen Ergebnismenge zu berechnen, ohne einen Cursor und eine temporäre Tabelle zu verwenden?

Ich verwende SQL Server 2000, würde mich aber auch für alle neuen Funktionen von 2005 und 2008 interessieren, die dabei helfen könnten.

War es hilfreich?

Lösung

Wenn die Identitätsspalte sequentiell ist, können Sie diesen Ansatz verwenden:

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

Andere Tipps

Hier ist Beispiel-SQL.Wenn Sie über eine Identitätsspalte verfügen, können Sie diese anstelle von „ActivityDate“ verwenden.

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)

Ich könnte „prev“ entfernen, habe es aber dort, vorausgesetzt, Sie benötigen IDs zum Löschen.

Hmm, interessante Herausforderung.Ich denke, Sie können es ohne Selbstverknüpfung tun, wenn Sie die neue Pivot-Funktionalität von 2005 verwenden.

Hier ist, was ich bisher habe. Ich wollte dem etwas mehr Zeit geben, bevor ich eine Antwort akzeptiere.

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

Ich möchte dies erweitern, damit ich maximal so viele Revisionen beibehalten und die älteren herausschneiden kann, während die erste, letzte und aktive Version weiterhin erhalten bleibt.Sollte durch die Klauseln „select top“ und „order by“ einfach genug sein, ähm ...und ActiveDate in die temporäre Tabelle einfügen.

Ich habe Peters Beispiel zum Laufen gebracht, habe es aber genommen und in eine Unterauswahl geändert.Ich habe mit beiden herumgespielt und der SQL-Trace zeigt, dass die Unterauswahl weniger Lesevorgänge durchführt.Aber es funktioniert, und ich werde ihn hochstimmen, wenn mein Ruf hoch genug ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top