【发布时间】:2011-08-23 18:28:48
【问题描述】:
我在这里有一个问题,看起来有点像我在搜索中找到的一些问题,但针对稍微不同的问题提供了解决方案,重要的是,这些问题在 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 的行,保留2007 年1 月3 日的信息,显示important_value 在2007 年1 月6 日更改,然后在2 再次显示相关更改-1-2007。
我目前的方法既笨拙又耗时,我知道一定有更好的方法。我编写了一个脚本,该脚本使用游标遍历 user_id 值(因为这会将巨大的表分解为可管理的部分),并为该用户创建一个仅包含行的临时表。然后为了获得连续的条目,它获取临时表,在临时表中没有其他条目且日期介于两个日期之间的条件下将其连接到自身。在下面的伪代码中,UDF_SameOrNull 是一个函数,如果传入的两个值相同或均为 NULL,则返回 1。
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() 以更优雅地查找连续条目。
感谢阅读。对于伪代码中的任何不必要的背景故事或错误,我深表歉意。
【问题讨论】:
-
对于 8GB 的表,您很可能会针对特定用户或用户子集发出查询。是这样吗?
-
是的,通常只有一个用户。要了解每个用户的数据,对于 7000 个用户,大约有 1000 万行。
标签: sql sql-server tsql sql-server-2000 date