重复记录在无限滚动时,排序随机

本文关键字:排序 随机 滚动 无限 记录 | 更新日期: 2023-09-27 18:02:29

我有一个无限滚动网页。我用随机记录喂养这个卷轴(我使用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);

重复记录在无限滚动时,排序随机

据我所知,对于大型表,使用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函数的一个属性是,每次在未被修改的行上使用它时,它都会返回相同的校验和数。因此,当它被自己使用时,查询的后续运行返回相同的"随机"行集。通常这是不可取的,但对于您的目的来说,这可能是可取的。为了使它对不同的用户更具随机性,您可以将BINARY_CHECKSUM(*)乘以RAND(?),并传入为该用户会话存储的种子。您还可能希望将BINARY_CHECKSUM中使用的列限制为不可更改的可预测列,如ID和created_at时间戳,并添加where ID>。

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

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

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

不幸的是,我不能尝试这个-让我知道它是否有效。

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

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

其中link_randomid是记录插入时生成的唯一随机id。