sourcetip

오라클 데이터베이스에서 무작위로 레코드를 가져오려면 어떻게 해야 합니까?

fileupload 2023. 3. 9. 22:17
반응형

오라클 데이터베이스에서 무작위로 레코드를 가져오려면 어떻게 해야 합니까?

Oracle DB에서 행을 랜덤으로 선택해야 합니다.

예: 100개의 행이 있는 테이블을 가정하면 100개의 행 전체에서 20개의 레코드를 랜덤으로 반환할 수 있습니다.

SELECT *
FROM   (
    SELECT *
    FROM   table
    ORDER BY DBMS_RANDOM.RANDOM)
WHERE  rownum < 21;

SAMPLE()은 정확히 20개의 행을 제공하는 것을 보증하지는 않지만 적절할 수 있습니다(또한 큰 테이블의 풀 쿼리 + 랜덤 정렬보다 훨씬 성능이 향상될 수 있습니다).

SELECT *
FROM   table SAMPLE(20);

★★★★★20필요한 행의 수가 아닌 대략적인 퍼센티지를 나타냅니다.이 경우 100개의 행이 있으므로 약 20개의 행을 얻으려면 20%의 표본이 필요합니다.

SELECT * FROM table SAMPLE(10) WHERE ROWNUM <= 20;

이것은 표를 정렬할 필요가 없기 때문에 더 효율적입니다.

SELECT column FROM
( SELECT column, dbms_random.value FROM table ORDER BY 2 )
where rownum <= 20;

요약하면, 두 가지 방법이 소개되었다.

1) using order by DBMS_RANDOM.VALUE clause
2) using sample([%]) function

첫 번째 방법은 'CORCTNESS'에서 유리하며, 두 번째 방법은 샘플링 중에 정보가 감소하기 때문에 쿼리 조건을 충족하는 사례가 있더라도 결과가 나오지 않을 수 있습니다.

두 번째 방법은 '효율적'이라는 장점이 있습니다. 즉, 더 빨리 결과를 얻을 수 있고 데이터베이스에 부하를 가볍게 할 수 있습니다.DBA로부터 첫 번째 방법을 사용한 쿼리가 데이터베이스에 부하를 준다는 경고를 받았습니다.

취향에 따라 두 가지 방법 중 하나를 선택할 수 있습니다!

큰 테이블의 경우 전체 테이블을 스캔해야 하고 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

즉, 전체 블록의 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;

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
      )
);

무작위로 20개의 열을 선택하려면 랜덤으로 정렬된 로트를 선택하고 그 세트의 첫 20개를 선택하는 것이 좋을 것 같습니다.

예를 들어 다음과 같습니다.

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

큰 데이터 청크를 선택하지 않기 위해 대부분의 데이터를 폐기하기 위해 작은 테이블에 가장 적합합니다.

각 그룹에서 랜덤 샘플을 선택하는 방법은 다음과 같습니다.

SELECT GROUPING_COLUMN, 
       MIN (COLUMN_NAME) KEEP (DENSE_RANK FIRST ORDER BY DBMS_RANDOM.VALUE) 
         AS RANDOM_SAMPLE
FROM TABLE_NAME
GROUP BY GROUPING_COLUMN
ORDER BY GROUPING_COLUMN;

얼마나 효율적인지는 모르겠지만, 카테고리나 서브카테고리가 많으면 이 방법이 효과가 있을 것 같습니다.

-- Q. 테이블에서 랜덤 50% 레코드를 찾는 방법은?

백분율 현명한 랜덤 데이터를 원할 때

* FROM (SELECT * FROM table_name ORDER BY DBMS_RANDOM)RANDOM) WHERNUM <= (table_name에서 카운트 선택) * 50/100;

언급URL : https://stackoverflow.com/questions/9868409/how-to-get-records-randomly-from-the-oracle-database

반응형