如何从oracle数据库中随机获取记录?

Bha*_*dra 68 oracle random select

我需要随机选择行.例如:让我们假设,一个表包含100条记录,但我需要从这100条记录中只获得20条记录,并且记录选择将随机出现..我将如何从中出来?我使用oracle作为我的数据库.任何建议都会对我有所帮助.提前致谢..

cag*_*boy 97

    SELECT *
    FROM   table
    ORDER BY DBMS_RANDOM.VALUE FETCH NEXT 20 ROWS ONLY;
Run Code Online (Sandbox Code Playgroud)

  • 你必须要知道这对大型表来说是一个非常繁重的操作,因为它首先会为EACH行分配一个随机数,然后对该值进行排序,然后从中获取一些记录. (9认同)
  • @NishantSharma,行是随机的,_then_ limited - 你的评论不正确. (8认同)
  • 这种方法非常慢 (4认同)

Jef*_*emp 42

SAMPLE()不能保证准确地为您提供20行,但可能是合适的(并且可能比完整查询表现更好+对于大表的随机排序):

SELECT *
FROM   table SAMPLE(20);
Run Code Online (Sandbox Code Playgroud)

注意:20这是一个近似的百分比,而不是所需的行数.在这种情况下,由于您有100行,要获得大约20行,您需要20%的样本.

  • 样本速度很快,但似乎不是很随机。靠近表格顶部/开头的记录往往受到青睐。 (2认同)
  • 抱歉,我犯了一个错误,您的帖子很好,结果平均分配。当您将“ where rownum <= 20”与sample(20)一起添加时,数据开始变得随机性降低。 (2认同)

gro*_*ter 12

SELECT * FROM table SAMPLE(10) WHERE ROWNUM <= 20;
Run Code Online (Sandbox Code Playgroud)

这样更有效,因为它不需要对表进行排序.

  • 在20行之后停止样本将导致非随机结果(表中较早找到的行将比后面的行返回的频率更高).此外,这不保证返回20行. (6认同)

Bis*_*han 9

SELECT column FROM
( SELECT column, dbms_random.value FROM table ORDER BY 2 )
where rownum <= 20;
Run Code Online (Sandbox Code Playgroud)


小智 8

如果表很大,按 dbms_random.value 排序的标准方法并不有效,因为您需要扫描整个表,而 dbms_random.value 的功能相当慢,并且需要上下文切换。对于这种情况,还有 3 种附加方法:


1:使用sample条款:

例如:

select *
from s1 sample block(1)
order by dbms_random.value
fetch first 1 rows only
Run Code Online (Sandbox Code Playgroud)

即获取所有块的 1%,然后对它们进行随机排序并仅返回 1 行。


2:如果您在正态分布的列上有索引/主键,您可以获得最小值和最大值,获得此范围内的随机值,并获得第一行的值大于或等于随机生成的值。

例子:

--big table with 1 mln rows with primary key on ID with normal distribution:
Create table s1(id primary key,padding) as 
   select level, rpad('x',100,'x')
   from dual 
   connect by level<=1e6;

select *
from s1 
where id>=(select 
              dbms_random.value(
                 (select min(id) from s1),
                 (select max(id) from s1) 
              )
           from dual)
order by id
fetch first 1 rows only;
Run Code Online (Sandbox Code Playgroud)

3:获取随机表块,生成rowid并通过该rowid从表中获取行

select * 
from s1
where rowid = (
   select
      DBMS_ROWID.ROWID_CREATE (
         1, 
         objd,
         file#,
         block#,
         1) 
   from    
      (
      select/*+ rule */ file#,block#,objd
      from v$bh b
      where b.objd in (select o.data_object_id from user_objects o where object_name='S1' /* table_name */)
      order by dbms_random.value
      fetch first 1 rows only
      )
);
Run Code Online (Sandbox Code Playgroud)


小智 6

总结一下,介绍了两种方式

1) using order by DBMS_RANDOM.VALUE clause
2) using sample([%]) function
Run Code Online (Sandbox Code Playgroud)

第一种方式在“正确性”方面具有优势,这意味着如果结果确实存在,您将永远不会失败,而在第二种方式中,即使有满足查询条件的案例,您也可能得不到结果,因为采样过程中信息会减少。

第二种方法在“高效”方面具有优势,这意味着您将更快地获得结果并减轻数据库的负载。DBA 向我发出警告,说我使用第一种方式的查询给数据库带来了负载

您可以根据自己的兴趣选择两种方式之一!


小智 5

要随机选择 20 行,我认为您最好选择随机排序的大量行,然后选择该组中的前 20 行。

就像是:

Select *
  from (select *
          from table
         order by dbms_random.value) -- you can also use DBMS_RANDOM.RANDOM
 where rownum < 21;
Run Code Online (Sandbox Code Playgroud)

最适用于小表,以避免选择大块数据而丢弃大部分数据。