一次只获取部分结果集,如何实现?

3

我正在使用查询来获取一个大约有500万行(每行10-15个列)的庞大结果集。由于没有ID列,甚至不能创建ID列(不是我的错),因此我无法根据ID分区数据,然后分批加载。更糟糕的是,这是SQL Server 2000,因此这个数据库可能没有大部分便利的SQL编码功能。是否有任何方法可以做到像这样 -

Select top 10000 column_list from myTable
then, select next top 10000 column_list from myTable (ie 10001 to 20000)
and so on...

rownumber是您想要使用的函数,但在2005年之前不可用。我认为除了非常笨拙的答案外,没有其他解决此问题的方法。另一种选择是创建一个进程(每晚运行?),将500万行写入具有ID列的新表中,然后从该表中进行报告。 - Twelfth
你有没有一个Date或者DateTime列呢? - William
@Twelfth - 我也考虑过这个,即使用一个暂存表。但是,建议我也避免使用它。虽然这不是最终决定,但应该避免这种情况。状况不佳。 - Steam
@William - 是的,William,我也在考虑这个问题。但问题是大多数行都在同一日期加载。所以,也许我需要按微秒或分钟进行分区。不太想这样做。 - Steam
1
无论如何,你并不孤单... http://www.codeproject.com/Articles/6936/Paging-of-Large-Resultsets-in-ASP-NET 如果你的数据集中没有“自然键”(比如日期时间戳+用户名+功能等),那么暂存表似乎是最好的选择(如果你能挑战它,请尽管挑战,我现在还不确定)。好奇谁会发现选择* 500万行,每次显示10k行有用...这些行的聚合可能更有益。也许重新审视一下为什么要这样做,是否有更好的解决方案来提供而不是5百万行的数据转储? - Twelfth
显示剩余2条评论
1个回答

2

如果有一个有用的索引,你可以通过跟踪基于该索引的值,一次抓取10000行。

假设有用的索引是 LastName + FirstName。

Select top 10000 column_list from MyTable 
order by LastName, FirstName

当你获取下一批10000行数据时,使用以下查询:

Select top 10000 column_list from MyTable 
where LastName >= PreviousLastname && FirstName > PreviousFirstname
order by LastName, FirstName

上面的伪代码假设组合中没有重复项,如果可能存在重复项,则最简单的方法是添加另一列(即使不索引),使其唯一。您需要在order by子句中使用第三列。
PreviousLastname是上一个查询的第10000条记录的值。
新增内容:
在这种情况下,有用的索引是具有高基数的任何索引--大多数是不同的值或最多是少量的非不同值。极其无用的索引将是像性别(M/F/null)这样的东西。
由于您将使用此数据进行数据加载,因此索引选择并不重要(忽略性能考虑),只要它具有高基数即可。请注意,索引和order by子句必须匹配,否则会给数据库带来沉重的负担。
修订--我发现了附加数据where子句中的一个明显错误。
where LastName >= PreviousLastname && FirstName > PreviousFirstname

这应该是:

where (LastName > PreviousLastname) 
   or (LastName = PreviousLastname && FirstName > PreviousFirstname) 

请告诉我什么是有用的索引,以及如何找出我是否已经拥有一个。 - Steam
更新答案以解释有用的索引。 - Gary Walker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接