SQL Server лучший способ рассчитать дату между текущей строкой и следующей строкой? - PullRequest
0 голосов
/ 09 сентября 2008

У меня следующая грубая структура:

Object -> Object Revisions -> Data

Данные могут быть разделены между несколькими объектами.

То, что я пытаюсь сделать, это очистить старые ревизии объектов. Я хочу сохранить первый, активный и разброс ревизий, чтобы сохранить последние изменения за определенный период времени. Данные могут сильно изменяться в течение 2 дней, а затем оставляться в покое на несколько месяцев, поэтому я хочу сохранить последнюю версию до начала изменений и до конца изменения нового набора.

В настоящее время я использую курсор и временную таблицу для хранения идентификаторов и даты между изменениями, чтобы я мог выбрать низко висящий фрукт, чтобы избавиться от него. Это означает использование @LastID, @LastDate, обновлений и вставок во временную таблицу и т. Д ...

Есть ли более простой / лучший способ вычислить разницу в дате между текущей строкой и следующей строкой в ​​моем начальном наборе результатов без использования курсора и временной таблицы?

Я на SQL Server 2000, но был бы заинтересован в любых новых функциях 2005, 2008, которые также могут помочь с этим.

Ответы [ 4 ]

4 голосов
/ 09 сентября 2008

Вот пример SQL. Если у вас есть столбец Identity, вы можете использовать его вместо «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)

Я мог бы удалить «prev», но он есть, если вам нужны идентификаторы для удаления.

1 голос
/ 14 января 2014

Если столбец идентификаторов является последовательным, вы можете использовать этот подход:

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

0 голосов
/ 09 сентября 2008

Вот что я получил, я хотел бы уделить этому немного больше времени, прежде чем принять ответ.

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

Я собираюсь расширить это, чтобы я мог сохранить максимальное количество ревизий и обрезать старые, сохраняя при этом первый, последний и активный. Должно быть достаточно просто с помощью выбора top и order by, um ... и вбрасывания ActiveDate во временную таблицу.

Я заставил пример Питера работать, но взял его и превратил в подселект. Я возился с обоими, и трассировка sql показывает, что вложенный выбор выполняет меньше операций чтения. Но это сработает, и я буду голосовать за него, когда получу достаточно высокую репутацию.

0 голосов
/ 09 сентября 2008

Хммм, интересный вызов. Я думаю, что вы можете сделать это без самостоятельного присоединения, если используете функциональность сводной таблицы новых версий 2005 года.

...