Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从SQL Server获取随机数据,但不重复值_Sql_Sql Server_Random_Shuffle_Random Data - Fatal编程技术网

从SQL Server获取随机数据,但不重复值

从SQL Server获取随机数据,但不重复值,sql,sql-server,random,shuffle,random-data,Sql,Sql Server,Random,Shuffle,Random Data,每次我需要从表中随机获取10行,但当我重复查询时,这些行永远不会重复 但若我得到所有的行,它将从一个重复,就像表有20行一样,第一次我得到10个随机行,第二次我需要得到剩余的10行,第三次查询我需要随机得到10行 当前我随机获取10行的查询: SELECT TOP 10 * FROM tablename ORDER BY NEWID() 但是MSDN建议这个查询 SELECT TOp 10 * FROM Table1 WHERE (ABS(CAST( (BINARY_CHECKSU

每次我需要从表中随机获取10行,但当我重复查询时,这些行永远不会重复

但若我得到所有的行,它将从一个重复,就像表有20行一样,第一次我得到10个随机行,第二次我需要得到剩余的10行,第三次查询我需要随机得到10行

当前我随机获取10行的查询:

SELECT TOP 10 * 
FROM tablename
ORDER BY NEWID() 
但是MSDN建议这个查询

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

为了好的表现。但此查询不返回常量行。请您对此提出一些建议,因为第二次查询所需的结果取决于第一次查询的随机结果,因此查询不能是无状态的。您需要以某种方式将有关先前查询的状态信息存储在某个位置


最简单的解决方案可能是将已经检索到的行或它们的ID存储在临时表中,然后查询。。。在第二个查询中,id不在select id from temp_表中。

正如Jiri Tosek所说,您运行的每个查询都必须知道以前的查询返回了什么

与其在表中插入以前返回的行的ID,然后检查新结果是否不在该表中,我只需向表中添加一列,其中包含定义新的随机行顺序的随机数

用随机数填充此列一次

这将记住行的随机顺序并使其稳定,因此在查询之间需要记住的只是迄今为止请求的随机行数。然后从上一个查询中停止的位置开始,根据需要获取尽可能多的行

将列RandomNumber binary8添加到表中。您可以选择不同的尺寸。8字节就足够了

用随机数填充它。一次

UPDATE tablename
SET RandomNumber = CRYPT_GEN_RANDOM(8)
在RandomNumber列上创建索引。唯一索引。如果发现有重复的随机数,这对于20000行和8字节长的随机数来说是不可能的,那么重新生成随机数再次运行UPDATE语句,直到它们都是唯一的

请求前10个随机行:

SELECT TOP(10) *
FROM tablename
ORDER BY RandomNumber
SELECT TOP(10) *
FROM tablename
WHERE RandomNumber > @VarLastRandomNumber
ORDER BY RandomNumber
在处理/使用这10个随机行时,请记住上次使用的随机数。最好的方法取决于如何处理这10个随机行

DECLARE @VarLastRandomNumber binary(8);
SET @VarLastRandomNumber = ... 
-- the random number from the last row returned by the previous query
请求下10个随机行:

SELECT TOP(10) *
FROM tablename
ORDER BY RandomNumber
SELECT TOP(10) *
FROM tablename
WHERE RandomNumber > @VarLastRandomNumber
ORDER BY RandomNumber
处理它们并记住最后使用的随机数


重复一遍。作为奖励,您可以在每次迭代中请求不同数量的随机行,而不必每次都是10行。

我要做的是有两个新字段,SELECTED int和timeselected integer

UPDATE tablename SET SELECTED = 0;

WITH CTE AS (SELECT TOP 10 * 
FROM tablename
ORDER BY TimesSelected  ASC, NEWID())
UPDATE CTE SET SELECTED = 1,  TimesSelected  = TimesSelected  + 1;

SELECT * from  tablename  WHERE SELECTED = 1; 
因此,如果每次都使用该选项,一旦选中,一条记录将进入堆的顶部,下面的记录将被随机选中

您可能希望在所选对象上放置索引,然后执行以下操作:

UPDATE tablename SET SELECTED = 0 WHERE SELECTED = 1;   -- for performance

如果您在一定时间内进行连续查询,最优雅的解决方案是使用光标:

DECLARE rnd_cursor CURSOR FOR 
  SELECT col1, col2, ... 
  FROM tablename
  ORDER BY NEWID(); 

OPEN rnd_cursor;  
FETCH NEXT FROM rnd_cursor;  -- Repeat ten times
保持光标处于打开状态,并根据需要继续获取行。完成后关闭光标:

CLOSE rnd_cursor;  
DEALLOCATE rnd_cursor;  
至于问题的第二部分,获取最后一行后,打开一个新光标:

IF @@FETCH_STATUS <> 0
BEGIN
  CLOSE rnd_cursor;
  OPEN rnd_cursor;
END;

请显示示例数据。数据非常大,比如我们有20000行和更多行,那么我们如何将数据存储到临时表中并反复运行,它会降低性能?对吗?是的,当您将记录添加到临时表时,它会降低性能,但是,如果您希望得到所需的结果,那么您唯一的选择就是将已选择的行存储在某个位置,也许一个带有索引的表可以为您提供足够的性能—20k行不是太多数据。例如,如果您的行具有整数ID,而您只存储已用行的ID,这可能意味着您的临时表可以容纳100kB,可以很容易地缓存在内存中,即使没有索引也可以快速访问。Msdn建议对此查询从表1中选择*,其中ABSCAST BINARY_CHECKSUM**RAND as int%100<10对于性能,我有一个简单的问题,我可以在此处附加条件,如id>10,我需要在二进制校验和之前或之后添加这个where条件是的,我认为这会起作用,一旦一个记录被选中并变成1,它就不能被重新选择,直到所有其他记录都变成1,当这种情况发生时,一些记录将变为2,然后不合格,直到其他记录以可行的方式赶上。如果a OP能够修改表本身,b表在整个过程中是稳定的,没有新的或删除的行,c一次只有一个会话执行此过程。OP没有提供任何具体细节,所以我们不知道。