SQL Server部分随机结果

SQL Server部分随机结果,sql,sql-server,random,pagination,sql-server-2012,Sql,Sql Server,Random,Pagination,Sql Server 2012,我正试图找到一种方法,从一个目前有129503条记录的表中随机抽取X条记录,并定期添加更多记录,但需要注意的是,我需要对它们进行分页,最好是在数据库级别。利用newid()将不起作用,因为不可能对结果集进行分页,因为它每次都会更改;利用TABLESAMPLE也不起作用,因为它不会每次都返回保证的记录集。我的一个想法是可能生成一个随机值(即newid()),它存储在这里的每个记录上,这样我就可以根据它进行初始排序(而不是动态生成),但是以一致的方式分页这些结果有点超出我的范围 可以这样想,因为我需

我正试图找到一种方法,从一个目前有129503条记录的表中随机抽取X条记录,并定期添加更多记录,但需要注意的是,我需要对它们进行分页,最好是在数据库级别。利用
newid()
将不起作用,因为不可能对结果集进行分页,因为它每次都会更改;利用
TABLESAMPLE
也不起作用,因为它不会每次都返回保证的记录集。我的一个想法是可能生成一个随机值(即
newid()
),它存储在这里的每个记录上,这样我就可以根据它进行初始排序(而不是动态生成),但是以一致的方式分页这些结果有点超出我的范围

可以这样想,因为我需要向每个访问我们站点的用户显示此表中的一组记录,但希望每个用户都有一个不同的视图(使其看起来像是随机的),然后需要可靠的分页来处理每个用户的记录,这样他们就不会得到上一页已经看到的结果


这是针对SQL Server 2012的,有什么想法吗?

现在这可能会很慢,因为会有多个函数调用,但您可以尝试:

ORDER BY HASHBYTES('SHA1', UserName + PrimaryKey), PrimaryKey
这个想法有三个部分。首先,HASHBYTES生成一致的随机输出。其次,在散列中包含用户名意味着每个用户将看到不同的列表。同时使用主键意味着每一行都将被唯一且一致地标识。如果发生意外的散列冲突,我们也只按PrimaryKey排序。
除了SHA1之外,您还可以使用不同的散列函数。我不太熟悉不同的散列函数,但我相信SHA1会很快。对于安全性和存储密码来说,这并不好,但对于订购来说应该没问题。

如果我理解正确,您会遇到一个棘手的问题。您希望每个用户有一组不同的记录,并且希望多个SQL调用之间的顺序是持久的。而且,表的大小可能在调用之间发生变化

一种简单的方法是枚举记录。然后,让每个用户从不同的偏移开始:

declare @offset int;

select @offset = rand() * count(*)
from table t;

with data as (
      select t.*, row_number() over (order by id) as rn,
             count(*) over () as numrecs
      from table t
     )
select t.*
from table t
order by mod(rn + @offset, numrecs);
然后可以使用带有乘法因子和偏移量的伪随机数生成器来增强这一点。最简单的方法是:

declare @offset int;

select @offset = rand(checksum(newid())) * count(*),
       @factor = rand(checksum(newid())) * count(*)
from table t;

with data as (
      select t.*, row_number() over (order by id) as rn,
             count(*) over () as numrecs
      from table t
     )
select t.*
from table t
order by mod(@factor * rn + @offset, numrecs);

如果
@因子
值是素数,则更安全。偶尔会出现
@因子
numrecs
的组合,这可能会导致结果中出现小周期。但是看看这是否满足您的需要。

我们在任何给定时间都有20个独立访客,因此我担心这一个会变得粗糙-特别是如果
@factor
应该是一个素数。当我说“独一无二”时,我的意思是在观看Google Analytics时,我们可以看到访问该网站的用户数量保持在20,但我们会看到它下降到18,然后跳到22,这是一个面向公众的网站,因此用户数量可能相当大。这近似于随机性,因为所有用户仍然看到相同的总顺序,只是起点不同。不确定是否可以接受。@usr。第一个只是从不同的偏移开始。第二种方法以不同的偏移量和不同的步长开始。这应该是足够随机的。我们不一定要为站点的这一特定部分提供用户名(它面向公众),但我可以很容易地替换会话启动时生成的GUID,这将为我解决这个问题。我还有另外一个想法要先考虑,如果不行的话,我下一步就试试。谢谢这张桌子有多大?对于小桌子来说,这当然是可行的。如果您负担不起在每个查询上对整个行进行排序,那么它将变得更加困难。129503行在我编写它时,现在是129510行。所以每隔一个小时左右就要添加一些东西。这个查询多久执行一次?让它运行100毫秒可以吗?如果是,您可以为每次执行对所有行进行排序。