Лучший способ SQL Server вычислить datediff между текущей строкой и следующей строкой?
-
09-06-2019 - |
Вопрос
У меня есть следующая приблизительная структура:
Object -> Object Revisions -> Data
Данные могут совместно использоваться несколькими объектами.
То, что я пытаюсь сделать, это очистить старые ревизии объектов.Я хочу сохранить первую, активную и разбросанную ревизии, чтобы сохранить последнее изменение за определенный период времени.Данные могут быть сильно изменены в течение 2 дней, а затем оставлены в покое на месяцы, поэтому я хочу сохранить последнюю ревизию до начала изменений и конечное изменение нового набора.
В настоящее время я использую курсор и временную таблицу для хранения идентификаторов и даты между изменениями, чтобы я мог выбрать низко висящие фрукты, от которых нужно избавиться.Это означает использование @lastID, @LastDate, обновлений и вставок во временную таблицу и т.д...
Есть ли более простой / лучший способ вычислить разницу в дате между текущей строкой и следующей строкой в моем исходном наборе результатов без использования курсора и временной таблицы?
Я работаю на sql server 2000, но был бы заинтересован в любых новых функциях 2005, 2008 годов, которые также могли бы помочь в этом.
Решение
Если столбец identity является последовательным, вы можете использовать этот подход:
SELECT curr.*, DATEDIFF(MINUTE, prev.EventDateTime,curr.EventDateTime) Duration FROM DWLog curr join DWLog prev on prev.EventID = curr.EventID - 1
Другие советы
Вот пример 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)
Я мог бы удалить "предыдущий", но имейте его там, предполагая, что вам нужны идентификаторы из него для удаления.
Хммм, интересная задача.Я думаю, вы можете сделать это без самостоятельного объединения, если используете новую для 2005 года функциональность pivot.
Вот что у меня есть на данный момент, я хотел бы уделить этому еще немного времени, прежде чем принимать ответ.
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
Я собираюсь расширить это, чтобы я мог сохранить как можно больше ревизий и удалить старые, сохранив при этом первую, последнюю и активную.Должно быть достаточно просто с помощью пунктов select top и order by, гм...и добавляю ActiveDate во временную таблицу.
Я заставил пример Питера сработать, но взял его и изменил на подвыборку.Я повозился с обоими, и трассировка sql показывает, что подвыборка выполняет меньше операций чтения.Но это действительно работает, и я проголосую за него, когда моя репутация будет достаточно высока.