Oracle veritabanından rastgele kayıtlar nasıl alınır?


82

Oracle DB'den rasgele satır seçmem gerekiyor.

Ör: 100 satırlık bir tablo varsayın, bu kayıtların 20'sini 100 satırın tamamından rastgele nasıl döndürebilirim.

Yanıtlar:


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

1
Beni yen. Ancak bu, tablodan yalnızca ilk 20 satırı seçecek ve bunları rastgele sıralayacaktır.
Nishant Sharma

10
Bunun büyük tablolarda çok ağır bir işlem olduğunu bilmelisiniz, çünkü önce HER satıra rastgele bir sayı atayacak, sonra bu değeri sıralayacak ve sonra ondan bazı kayıtlar alacak.
Roeland Van Heddegem

11
@NishantSharma, satırlar rastgele hale getirilir, ardından sınırlandırılır - yorumunuz doğru değil.
Simon MᶜKenzie

6
Bu yaklaşım ÇOK yavaş
Evan Kroske

1
@JonBetts, bence örnek çok daha hızlı ve kaynak açısından daha verimli: stackoverflow.com/a/9920431/156787
Evan Kroske

50

SAMPLE () öğesinin size tam olarak 20 satır vereceği garanti edilmez , ancak uygun olabilir (ve büyük tablolar için tam bir sorgu + rasgele sırala göre önemli ölçüde daha iyi performans gösterebilir):

SELECT *
FROM   table SAMPLE(20);

Not: 20Burada istenen satır sayısı değil, yaklaşık bir yüzde verilmiştir. Bu durumda, 100 satırınız olduğundan, yaklaşık 20 satır elde etmek için% 20'lik bir örnek istersiniz.


1
örnek hızlıdır ancak çok rastgele görünmemektedir. tablonun başına / üstüne doğru kayıtlar tercih edilme eğilimindedir.
craigrs84

1
Bu, sorguyu tüm tabloyu geçmeden durdurursanız gerçekleşir.
Jeffrey Kemp

2
Üzgünüm bir hata yaptım, gönderiniz iyi ve sonuçlar eşit olarak dağıtıldı. Örnek (20) ile birlikte "where rownum <= 20" eklediğinizde veriler daha az rastgele hale gelmeye başlar.
craigrs84

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

Tabloyu sıralaması gerekmediği için bu daha verimlidir.


7
Örneği 20 satır sonra durdurmak rastgele olmayan sonuçlarla sonuçlanacaktır (tabloda daha önce bulunan satırlar sonrakilere göre çok daha sık döndürülecektir). Ayrıca, bunun 20 satır döndürmesi garanti edilmez.
Jeffrey Kemp

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

4

20 sırayı rastgele seçmek için bence bunların çoğunu rastgele sırayla seçip bu setin ilk 20'sini seçmeniz daha iyi olur.

Gibi bir şey:

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

Küçük tablolar için, yalnızca çoğunu atmak için büyük veri yığınlarını seçmekten kaçınmak için kullanılır.


3

Özetle, iki yol tanıtıldı

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

Birinci yolun 'DOĞRULUK' avantajına sahiptir, bu da gerçekten varsa sonuç almada asla başarısız olmayacağınız anlamına gelirken, ikinci yöntemde, örnekleme sırasında bilgi azaldığından sorgu koşulunu karşılayan durumlar olsa bile sonuç alamazsınız.

İkinci yolun 'ETKİLİ' avantajı vardır, bu da daha hızlı sonuç alacağınız ve veri tabanınıza hafif yük vereceğiniz anlamına gelir. DBA'dan ilk yolu kullanan sorgumun veritabanına yükler verdiğine dair bir uyarı aldım

İlginize göre iki yoldan birini seçebilirsiniz!


1

Büyük tablolar söz konusu olduğunda, dbms_random.value'ya göre sıralama ile standart yol etkili değildir çünkü tüm tabloyu taramanız gerekir ve dbms_random.value oldukça yavaş bir işlevdir ve bağlam anahtarları gerektirir. Bu tür durumlar için 3 ek yöntem vardır:


1: Kullanım samplemaddesi:

Örneğin:

select *
from s1 sample block(1)
order by dbms_random.value
fetch first 1 rows only

yani, tüm blokların% 1'ini alın, sonra bunları rastgele sıralayın ve yalnızca 1 satır döndürün.


2: normal dağılıma sahip sütunda bir dizin / birincil anahtarınız varsa varsa, minimum ve maksimum değerleri alabilir, bu aralıkta rastgele değer alabilir ve rastgele oluşturulan bu değerden daha büyük veya ona eşit bir değere sahip ilk satırı elde edebilirsiniz.

Misal:

--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: rastgele tablo bloğu alın, satır kimliği oluşturun ve bu satır kimliği ile tablodan satır alın :

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

0

Her gruptan rastgele bir örnek seçmenin yolu:

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;

Ne kadar verimli olduğundan emin değilim, ancak çok sayıda kategori ve alt kategoriniz varsa, bu işi iyi yapıyor gibi görünüyor.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.