0

我有一个无限滚动的网页。我正在用随机记录喂这个卷轴(我正在使用order by newid()它)。当滚动到达末尾时,有一个 ajax 调用会在页面上附加新的随机数据。显然,我用这种方法得到了重复的记录。这是我的问题:有没有办法避免重复记录?我应该将已经加载到页面的记录存储在某处并将它们从选择中排除吗?或者我应该选择带有随机记录的巨大记录集,将其保存在内存中,然后用这个记录集的块提供页面?随机无限滚动的正确方法是什么?提前致谢!

编辑

要求的代码:

数据提供者:

res = data.OrderBy(l => Guid.NewGuid()).Take(numberOfRecords);

客户:

$.get("/Start/Index/", function (data) {
                if (data != '') {                        
                    isLoading = false;
                    $("#tiles").append(data);});

服务器:

model.PageData = _dataProvider.GetOnePage(recordsPerPage);
return PartialView("_MyView", model.PageData);
4

2 回答 2

0

据我了解,对于大型表,使用 newid 并不快——SqlServer 必须先为表中的每一行分配一个随机值,然后才能进行排序。这篇 MSDN 文章有一个小讨论:http: //msdn.microsoft.com/en-us/library/cc441928.aspx

要在每次运行查询时获得“相同的随机结果”,您需要计算和存储订单,或者根据您存储的种子使其可预测。

你可以尝试这样的事情:

  SELECT * FROM Table1
  WHERE (ABS(CAST(
  (BINARY_CHECKSUM(*)) as int)) % 100) < 10

BINARY_CHECKSUM 函数的一个属性是,每次在未修改的行上使用它时,它都会返回相同的校验和数。因此,当它单独使用时,查询的后续运行会返回相同的“随机”行集。通常这是不可取的,但出于您的目的,它可能是可取的。为了使其对不同用户更加随机,您可以通过 RAND(?) 多次 BINARY_CHECKSUM(*) 并传入您为该用户会话存储的种子。您还可能希望将 BINARY_CHECKSUM 中使用的列限制为可预测且不会更改的内容,例如 ID 和 created_at 时间戳,并添加 where id > 。

把它们放在一起,查询可能看起来像这样:

  SELECT * FROM Table1
  WHERE id > ? AND (ABS(CAST(
  (BINARY_CHECKSUM(*) * RAND(?)) as int)) % 100) < 10

然后传入两个参数:第一次显示无限滚动时的最大 id 和当时生成的种子。

不幸的是,我无法尝试 - 如果它有效,请告诉我。

于 2013-03-05T20:36:55.187 回答
0

经过 2 天的研究,我发现没有简单的方法可以在没有重复记录的情况下进行随机无限滚动。我决定如果我不能做随机滚动,我必须做看起来像随机的滚动,但实际上不是。所以最终得到了这个解决方案:

data = data.OrderByDescending(link => EntityFunctions.TruncateTime(link.link_timestamp)).OrderBy(l => l.link_randomid).Skip(skip).Take(numberOfRecords);

其中 link_randomid 是在记录插入时生成的唯一随机 id。希望这会为某人节省一些时间。

于 2013-03-06T17:02:38.080 回答