3

我每次需要从表中随机获取 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 

为了良好的表现。但是这个查询不返回常量行。你能在这方面提出一些建议吗

4

4 回答 4

2

由于第二个查询的所需结果取决于第一个查询的(随机)结果,因此查询不能是无状态的。您需要以某种方式将状态(有关先前查询/查询的信息)存储在某处。

最简单的解决方案可能是将已经检索到的行或其 ID 存储在临时表中,然后... where id not in (select id from temp_table)在第二个查询中进行查询。

于 2016-07-26T11:17:47.883 回答
0

我要做的是有两个新字段,SELECTED (int) 和 TimesSelected (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; 

因此,如果您每次都使用它,则一旦选择了一条记录,就会进入堆的顶部,并且它下面的记录是随机选择的。

您可能想在 SELECTED 上放置一个索引并执行

UPDATE tablename SET SELECTED = 0 WHERE SELECTED = 1;   -- for performance
于 2016-07-26T13:14:43.203 回答
0

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

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;
于 2016-07-26T13:27:04.797 回答
0

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

我不是在表中插入先前返回的行的 ID,然后检查新结果是否不在该表中,而是简单地向表中添加一列,其中包含将定义新的随机行顺序的随机数。

您使用随机数填充此列一次。

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


向表中添加一列RandomNumber binary(8)。您可以选择不同的尺寸。8 个字节应该足够了。

用随机数填充它。一次。

UPDATE tablename
SET RandomNumber = CRYPT_GEN_RANDOM(8)

RandomNumber在列上创建索引。唯一索引。如果事实证明存在重复的随机数(这对于 20,000 行和 8 字节长的随机数来说不太可能),则重新生成随机数(UPDATE再次运行该语句),直到它们都是唯一的。

请求前 10 个随机行:

SELECT TOP(10) *
FROM tablename
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
WHERE RandomNumber > @VarLastRandomNumber
ORDER BY RandomNumber

处理它们并记住最后使用的随机数。

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

于 2016-07-26T12:54:16.147 回答