我有一个无限滚动的网页。我正在为这个卷轴提供随机记录(我正在使用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);
答案 0 :(得分: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&gt;
总而言之,查询可能如下所示:
SELECT * FROM Table1
WHERE id > ? AND (ABS(CAST(
(BINARY_CHECKSUM(*) * RAND(?)) as int)) % 100) < 10
你传递了两个参数:第一次显示无限滚动时的最大ID和你当时生成的种子。
不幸的是,我无法尝试这一点 - 让我知道它是否有效。
答案 1 :(得分:0)
经过2天的研究,我发现在没有重复记录的情况下,没有简单的方法可以进行随机无限滚动。我决定如果我不能做随机滚动我必须做滚动,看起来像随机,但实际上不是。所以最终得到了这个解决方案:
data = data.OrderByDescending(link => EntityFunctions.TruncateTime(link.link_timestamp)).OrderBy(l => l.link_randomid).Skip(skip).Take(numberOfRecords);
其中link_randomid是在记录插入时生成的唯一随机ID。 希望这会为某人节省一些时间。