У меня есть вопрос, который немного похож на некоторые из тех, что я нашел в поиске, но с решениями для немного других проблем и, что важно, которые не работают в SQL 2000.
У меня есть очень большая таблица с большим количеством избыточных данных, которые я пытаюсь сократить до просто полезных записей.Это таблица истории, и как она работает, если две записи по сути являются дублирующими и последовательными при сортировке по дате, последняя может быть удалена.Данные из более ранней записи будут использоваться при запросе исторических данных от даты между датой вступления в силу этой записи и следующей неповторяющейся записью.
Данные выглядят примерно так:
id user_id effective_date important_value useless_value
1 1 1/3/2007 3 0
2 1 1/4/2007 3 1
3 1 1/6/2007 NULL 1
4 1 2/1/2007 3 0
5 2 1/5/2007 12 1
6 3 1/1/1899 7 0
С этим набором образцов мы будем рассматривать две последовательные копии строк, если user_id
и important_value
одинаковы.Из этого набора образцов мы удалили только строку с id
= 2, сохранив информацию за 1-3-2007, показав, что important_value
изменился за 1-6-2007, а затем снова показав соответствующее изменение 2-1-2007.
Мой нынешний подход неудобен и отнимает много времени, и я знаю, что должен быть лучший путь.Я написал скрипт, который использует курсор для перебора значений user_id
(поскольку он разбивает огромную таблицу на управляемые части) и создает временную таблицу, состоящую только из строк для этого пользователя.Затем, чтобы получить последовательные записи, он берет временную таблицу, присоединяет ее к себе при условии, что в временной таблице нет других записей с датой между двумя датами.В приведенном ниже псевдокоде UDF_SameOrNull
- это функция, которая возвращает 1, если два переданных значения одинаковы или оба имеют значение NULL.
WHILE (@@fetch_status <> -1)
BEGIN
SELECT * FROM History INTO #history WHERE user_id = @UserId
--return entries to delete
SELECT h2.id
INTO #delete_history_ids
FROM #history h1
JOIN #history h2 ON
h1.effective_date < h2.effective_date
AND dbo.UDF_SameOrNull(h1.important_value, h2.important_value)=1
WHERE NOT EXISTS (SELECT 1 FROM #history hx WHERE hx.effective_date > h1.effective_date and hx.effective_date < h2.effective_date)
DELETE h1
FROM History h1
JOIN #delete_history_ids dh ON
h1.id = dh.id
FETCH NEXT FROM UserCursor INTO @UserId
END
Она также циклически повторяет один и тот же набор дубликатов до тех пор, покаих нет, поскольку удаление строк создает новые последовательные пары, которые потенциально могут быть обмануты.Я упустил это для простоты.
К сожалению, я должен использовать SQL Server 2000 для этой задачи, и я почти уверен, что он не поддерживает ROW_NUMBER () для более элегантного способа поиска последовательных записей.
Спасибо за чтение.Я прошу прощения за любые ненужные предысторию или ошибки в псевдокоде.