Bagaimana cara meminta baris acak dalam SQL?

510

Bagaimana saya bisa meminta baris acak (atau sedekat mungkin dengan acak) dalam SQL murni?

sverrejoh
sumber
i digunakan untuk selalu melakukan hal ini di php setelah hasil query dari sql ... ini mungkin jauh lebih cepat untuk pengolahan per solusi ini batas 1 embel
CheeseConQueso
2
Tampaknya tidak ada solusi "SQL murni" yang berjalan di setiap dbms ... ada solusi untuk masing-masing.
Manu
Versi kinerja: stackoverflow.com/questions/4329396/…
Ciro Santilli 郝海东 冠状 病 六四 六四 事件 法轮功

Jawaban:

735

Lihat posting ini: SQL untuk Memilih baris acak dari tabel database . Itu melewati metode untuk melakukan ini di MySQL, PostgreSQL, Microsoft SQL Server, IBM DB2 dan Oracle (berikut ini disalin dari tautan itu):

Pilih baris acak dengan MySQL:

SELECT column FROM table
ORDER BY RAND()
LIMIT 1

Pilih baris acak dengan PostgreSQL:

SELECT column FROM table
ORDER BY RANDOM()
LIMIT 1

Pilih baris acak dengan Microsoft SQL Server:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

Pilih baris acak dengan IBM DB2

SELECT column, RAND() as IDX 
FROM table 
ORDER BY IDX FETCH FIRST 1 ROWS ONLY

Pilih catatan acak dengan Oracle:

SELECT column FROM
( SELECT column FROM table
ORDER BY dbms_random.value )
WHERE rownum = 1
Yaakov Ellis
sumber
30
-1 untuk mengandalkan order by rand()atau setara dalam semua dbs: |. juga disebutkan di sini .
AD7six
20
Sepuluh tahun yang lalu beberapa pria mengatakan bahwa menggunakan ORDER BY RAND()itu salah ...
trejder
ORDER BY NEWID () tampaknya jauh lebih lambat di SQL Server. Kueri saya terlihat seperti: pilih 1.000 C.CustomerId, CL.LoginName dari Pelanggan C bergabung dengan LinkedAccount LA di C.CustomerId = LA.CustomerId bergabung dengan CustomerLogin CL di C.CustomerId = CL.CustomerId grup oleh C.CustomerId, CL. LoginName memiliki hitungan (*)> 1 pesanan oleh NEWID () Menghapus baris "pesanan oleh NEWID ()" mengembalikan hasil yang jauh lebih cepat.
Ben Power
3
Untuk SQLite gunakan fungsi RANDOM ().
Slam
10
Solusi ini tidak berskala. Mereka O(n)dengan nmenjadi jumlah catatan dalam tabel. Bayangkan Anda memiliki 1 juta catatan, apakah Anda benar-benar ingin menghasilkan 1 juta angka acak atau id unik? Saya lebih suka menggunakan COUNT()dan melibatkan itu dalam LIMITekspresi baru dengan nomor acak tunggal.
Christian Hujer
174

Solusi seperti Jeremies:

SELECT * FROM table ORDER BY RAND() LIMIT 1

bekerja, tetapi mereka membutuhkan pemindaian berurutan dari semua tabel (karena nilai acak yang terkait dengan setiap baris perlu dihitung - sehingga yang terkecil dapat ditentukan), yang bisa sangat lambat bahkan untuk tabel berukuran sedang. Rekomendasi saya adalah menggunakan semacam kolom angka yang diindeks (banyak tabel memiliki ini sebagai kunci utama mereka), dan kemudian menulis sesuatu seperti:

SELECT * FROM table WHERE num_value >= RAND() * 
    ( SELECT MAX (num_value ) FROM table ) 
ORDER BY num_value LIMIT 1

Ini berfungsi dalam waktu logaritmik, terlepas dari ukuran tabel, jika num_valuediindeks. Satu peringatan: ini mengasumsikan bahwa num_valueterdistribusi secara merata dalam kisaran 0..MAX(num_value). Jika dataset Anda sangat menyimpang dari asumsi ini, Anda akan mendapatkan hasil yang miring (beberapa baris akan muncul lebih sering daripada yang lain).

Grey Panther
sumber
8
Saran kedua tidak acak. Anda tidak dapat memprediksi baris yang akan dipilih, tetapi jika Anda harus bertaruh, Anda akan bertaruh pada baris kedua. Dan Anda tidak akan pernah bertaruh pada baris terakhir, semakin kecil kemungkinannya untuk memilih apa pun distribusi num_value Anda dan seberapa besar tabel Anda.
Etienne Racine
1
Saya tahu bahwa biasanya fungsi RAND () tidak berkualitas sangat tinggi, tetapi selain itu dapatkah Anda menjelaskan mengapa pemilihannya tidak acak?
Grey Panther
13
Yang pertama adalah SALAH dalam SQL Server. Fungsi RAND () dipanggil hanya sekali per kueri, tidak satu kali per baris. Jadi selalu memilih baris pertama (coba).
Jeff Walker Code Ranger
3
Yang kedua juga mengasumsikan bahwa semua baris diperhitungkan: mungkin saja akan memilih baris yang telah dihapus.
Sam Rueby
3
@ Sam.Rueby Sebenarnya, num_value> = RAND () ... limit 1 memastikan bahwa baris kosong akan dilewati sampai menemukan baris yang ada.
ghord
62

Saya tidak tahu seberapa efisien ini, tetapi saya telah menggunakannya sebelumnya:

SELECT TOP 1 * FROM MyTable ORDER BY newid()

Karena GUID cukup acak, pemesanan berarti Anda mendapatkan baris acak.

Matt Hamilton
sumber
1
Saya menggunakan server MS SQL, SELECT TOP 1 * FROM some_table_name ORDER BY NEWID () bekerja sangat baik untuk saya, terima kasih atas sarannya guys!
Itu persis sama denganORDER BY RAND() LIMIT 1
Ken Bloom
6
Ini juga sangat spesifik karena menggunakan TOP 1dan newid().
Gray
12
Ini ide yang buruk. Metode ini tidak akan menggunakan indeks kecuali setiap kolom diindeks secara individual. Tabel dengan 100 juta catatan bisa memakan waktu yang sangat lama untuk mendapatkan satu catatan.
Beralih
1
@Switch dan solusi apa yang akan Anda usulkan?
Akmal Salikhov
31
ORDER BY NEWID()

mengambil 7.4 milliseconds

WHERE num_value >= RAND() * (SELECT MAX(num_value) FROM table)

mengambil 0.0065 milliseconds!

Saya pasti akan menggunakan metode yang terakhir.

Neel
sumber
2
Opsi kedua tidak akan memilih baris terakhir. Saya tidak tahu mengapa - hanya menunjukkannya.
Voldemort
7
@Oldemort: rand()mengembalikan angka titik-mengambang di nmana 0 < n < 1. Dengan asumsi num_valuebilangan bulat, nilai pengembalian dari rand() * max(num_value)juga akan dipaksa ke bilangan bulat, sehingga memotong apa pun setelah titik desimal. Karenanya, rand() * max(num_value)akan selalu kurang dari max(num_value), itulah sebabnya baris terakhir tidak akan pernah dipilih.
Ian Kemp
Saya tidak akan efisien jika data saya sering dihapus - jika saya menemukan celah, saya harus menjalankan kembali seluruh permintaan.
Loic Coenen
1
@IanKemp pertanyaan bodoh, lalu mengapa tidak menggunakan SELECT MAX (num_value) +1? Karena rand (atau ACAK dalam kebanyakan kasus) mengembalikan [0,1), Anda akan mendapatkan rentang nilai penuh. Juga, ya, Anda benar, harus memperbaiki kueri.
tekHedd
13

Anda tidak mengatakan server mana yang Anda gunakan. Di versi SQL Server yang lebih lama, Anda dapat menggunakan ini:

select top 1 * from mytable order by newid()

Di SQL Server 2005 dan lebih tinggi, Anda bisa menggunakan TABLESAMPLEuntuk mendapatkan sampel acak yang dapat diulang:

SELECT FirstName, LastName
FROM Contact 
TABLESAMPLE (1 ROWS) ;
Jon Galloway
sumber
9
MSDN mengatakan newid () lebih disukai daripada tablesample untuk hasil yang benar-benar acak: msdn.microsoft.com/en-us/library/ms189108.aspx
Andrew Hedges
7
@Andrew Hedges: ORDER BY NEWID () terlalu mahal
Andrei Rînea
10

Untuk SQL Server

newid () / order by akan berfungsi, tetapi akan sangat mahal untuk set hasil yang besar karena harus menghasilkan id untuk setiap baris, dan kemudian mengurutkannya.

TABLESAMPLE () bagus dari sudut pandang kinerja, tetapi Anda akan mendapatkan hasil yang berkelompok (semua baris pada halaman akan dikembalikan).

Untuk sampel acak benar yang berkinerja lebih baik, cara terbaik adalah menyaring baris secara acak. Saya menemukan contoh kode berikut dalam artikel SQL Server Books Online yang Membatasi Set Hasil dengan Menggunakan TABLESAMPLE :

Jika Anda benar-benar ingin sampel acak baris individual, ubah kueri Anda untuk memfilter baris secara acak, alih-alih menggunakan TABLESAMPLE. Misalnya, kueri berikut menggunakan fungsi NEWID untuk mengembalikan sekitar satu persen dari baris tabel Sales.SalesOrderDetail:

SELECT * FROM Sales.SalesOrderDetail
WHERE 0.01 >= CAST(CHECKSUM(NEWID(),SalesOrderID) & 0x7fffffff AS float)
              / CAST (0x7fffffff AS int)

Kolom SalesOrderID termasuk dalam ekspresi CHECKSUM sehingga NEWID () mengevaluasi satu kali per baris untuk mencapai pengambilan sampel pada basis per baris. Ekspresi CAST (CHECKSUM (NEWID (), SalesOrderID) & 0x7fffffff AS float / CAST (0x7fffffff AS int) mengevaluasi nilai float acak antara 0 dan 1.

Saat dijalankan melawan tabel dengan 1.000.000 baris, berikut ini adalah hasil saya:

SET STATISTICS TIME ON
SET STATISTICS IO ON

/* newid()
   rows returned: 10000
   logical reads: 3359
   CPU time: 3312 ms
   elapsed time = 3359 ms
*/
SELECT TOP 1 PERCENT Number
FROM Numbers
ORDER BY newid()

/* TABLESAMPLE
   rows returned: 9269 (varies)
   logical reads: 32
   CPU time: 0 ms
   elapsed time: 5 ms
*/
SELECT Number
FROM Numbers
TABLESAMPLE (1 PERCENT)

/* Filter
   rows returned: 9994 (varies)
   logical reads: 3359
   CPU time: 641 ms
   elapsed time: 627 ms
*/    
SELECT Number
FROM Numbers
WHERE 0.01 >= CAST(CHECKSUM(NEWID(), Number) & 0x7fffffff AS float) 
              / CAST (0x7fffffff AS int)

SET STATISTICS IO OFF
SET STATISTICS TIME OFF

Jika Anda bisa menggunakan TABLESAMPLE, itu akan memberi Anda kinerja terbaik. Kalau tidak, gunakan metode newid () / filter. newid () / order oleh harus menjadi pilihan terakhir jika Anda memiliki set hasil yang besar.

Rob Boek
sumber
4

Jika memungkinkan, gunakan pernyataan tersimpan untuk menghindari inefisiensi kedua indeks pada RND () dan membuat bidang nomor catatan.

SIAPKAN RandomRecord DARI "SELECT * FROM table LIMIT?, 1";
SET @ n = LANTAI (RAND () * (SELECT COUNT (*) FROM table));
EXECUTE RandomRecord MENGGUNAKAN @n;
Cari
sumber
Solusi ini juga menangani pengembalian baris acak ketika nilai numerik yang diindeks digunakan di mana klausa di atas tidak terdistribusi secara merata; jadi walaupun itu membutuhkan waktu yang hampir sama (konstan) dengan menggunakan mana id_value> = RAND () * MAX (id_value), itu lebih baik.
guido
Sejauh yang saya tahu ini tidak berjalan dalam waktu yang konstan, itu berjalan dalam waktu linier. Dalam kasus terburuk, @n sama dengan jumlah baris dalam tabel, dan "SELECT * FROM table LIMIT?, 1" mengevaluasi @n - 1 baris hingga mencapai yang terakhir.
Andres Riofrio
3

Cara terbaik adalah meletakkan nilai acak di kolom baru hanya untuk tujuan itu, dan menggunakan sesuatu seperti ini (pseude code + SQL):

randomNo = random()
execSql("SELECT TOP 1 * FROM MyTable WHERE MyTable.Randomness > $randomNo")

Ini adalah solusi yang digunakan oleh kode MediaWiki. Tentu saja, ada beberapa bias terhadap nilai yang lebih kecil, tetapi mereka menemukan bahwa itu cukup untuk membungkus nilai acak menjadi nol ketika tidak ada baris yang diambil.

solusi newid () mungkin memerlukan pemindaian tabel penuh sehingga setiap baris dapat diberi panduan baru, yang akan jauh lebih sedikit performanya.

rand () solusi mungkin tidak berfungsi sama sekali (yaitu dengan MSSQL) karena fungsi akan dievaluasi sekali saja, dan setiap baris akan diberi nomor "acak" yang sama.

Ishmaeel
sumber
1
Melilit saat Anda mendapatkan 0 hasil memberikan sampel acak yang terbukti (bukan hanya "cukup baik"). Solusi ini hampir mencapai permintaan multi-baris (pikirkan "pengocokan partai"). Masalahnya adalah bahwa hasilnya cenderung dipilih dalam kelompok yang sama berulang kali. Untuk menyiasatinya, Anda perlu mendistribusikan kembali nomor acak yang baru saja Anda gunakan. Anda dapat menipu dengan melacak randomNo dan mengaturnya ke maks (keacakan) dari hasil, tetapi kemudian p (baris i pada kueri 1 DAN baris i pada kueri 2) == 0, yang tidak adil. Biarkan saya melakukan beberapa matematika, dan saya akan kembali kepada Anda dengan skema yang benar-benar adil.
alsuren
3

Untuk SQL Server 2005 dan 2008, jika kita ingin sampel acak dari masing-masing baris (dari Books Online ):

SELECT * FROM Sales.SalesOrderDetail
WHERE 0.01 >= CAST(CHECKSUM(NEWID(), SalesOrderID) & 0x7fffffff AS float)
/ CAST (0x7fffffff AS int)
Santiago Cepas
sumber
3

Insted menggunakan RAND (), karena tidak dianjurkan , Anda cukup mendapatkan ID maks (= Max):

SELECT MAX(ID) FROM TABLE;

dapatkan secara acak antara 1..Max (= My_Generated_Random)

My_Generated_Random = rand_in_your_programming_lang_function(1..Max);

dan kemudian jalankan SQL ini:

SELECT ID FROM TABLE WHERE ID >= My_Generated_Random ORDER BY ID LIMIT 1

Perhatikan bahwa ia akan memeriksa setiap baris yang Idnya EQUAL atau LEBIH TINGGI dari nilai yang dipilih. Dimungkinkan juga untuk mencari baris di tabel, dan mendapatkan ID yang sama atau lebih rendah daripada My_Generated_Random, lalu ubah kueri seperti ini:

SELECT ID FROM TABLE WHERE ID <= My_Generated_Random ORDER BY ID DESC LIMIT 1
forsberg
sumber
Apa yang akan terjadi jika ID acak yang dihasilkan tidak ada dalam tabel lagi? Baris yang dihapus atau pasif yang tidak ingin Anda tampilkan kepada pengguna akan menyebabkan masalah.
Ebleme
Tidak ada. Anda mendapatkan nomor id TERTUTUP, tidak tepat,. Jika Anda menganggap id = 1 akan dihapus, tukar 1 dengan minimum.
forsberg
2

Seperti yang ditunjukkan dalam komentar @ BillKarwin pada jawaban @ cnu ...

Ketika menggabungkan dengan LIMIT, saya telah menemukan bahwa kinerjanya jauh lebih baik (setidaknya dengan PostgreSQL 9.1) untuk BERGABUNG dengan pemesanan acak daripada langsung memesan baris aktual: misalnya

SELECT * FROM tbl_post AS t
JOIN ...
JOIN ( SELECT id, CAST(-2147483648 * RANDOM() AS integer) AS rand
       FROM tbl_post
       WHERE create_time >= 1349928000
     ) r ON r.id = t.id
WHERE create_time >= 1349928000 AND ...
ORDER BY r.rand
LIMIT 100

Pastikan saja bahwa 'r' menghasilkan nilai 'rand' untuk setiap nilai kunci yang mungkin dalam kueri kompleks yang digabungkan dengannya tetapi masih membatasi jumlah baris 'r' jika memungkinkan.

CAST sebagai Integer sangat membantu untuk PostgreSQL 9.2 yang memiliki optimasi pengurutan khusus untuk tipe floating dan integer presisi tunggal.

karmakaze
sumber
1

Sebagian besar solusi di sini bertujuan untuk menghindari penyortiran, tetapi mereka masih perlu melakukan pemindaian berurutan di atas tabel.

Ada juga cara untuk menghindari pemindaian berurutan dengan beralih ke pemindaian indeks. Jika Anda tahu nilai indeks dari baris acak Anda, Anda bisa mendapatkan hasilnya hampir secara instan. Masalahnya adalah - bagaimana menebak nilai indeks.

Solusi berikut ini berfungsi pada PostgreSQL 8.4:

explain analyze select * from cms_refs where rec_id in 
  (select (random()*(select last_value from cms_refs_rec_id_seq))::bigint 
   from generate_series(1,10))
  limit 1;

Saya solusi di atas Anda menebak 10 berbagai nilai indeks acak dari kisaran 0 .. [nilai terakhir id].

Angka 10 arbitrer - Anda dapat menggunakan 100 atau 1000 karena (luar biasa) tidak memiliki dampak besar pada waktu respons.

Ada juga satu masalah - jika Anda memiliki id jarang Anda mungkin kehilangan . Solusinya adalah memiliki rencana cadangan :) Dalam hal ini pesanan lama murni dengan permintaan acak (). Ketika gabungan id terlihat seperti ini:

explain analyze select * from cms_refs where rec_id in 
    (select (random()*(select last_value from cms_refs_rec_id_seq))::bigint 
     from generate_series(1,10))
    union all (select * from cms_refs order by random() limit 1)
    limit 1;

Bukan klausa SEMUA serikat buruh . Dalam hal ini jika bagian pertama mengembalikan data apa pun, bagian kedua TIDAK PERNAH dieksekusi!

hegemon
sumber
1

Pada akhirnya, tetapi tiba di sini melalui Google, jadi demi keturunan, saya akan menambahkan solusi alternatif.

Pendekatan lain adalah menggunakan TOP dua kali, dengan pesanan bergantian. Saya tidak tahu apakah itu "SQL murni", karena menggunakan variabel di TOP, tetapi berfungsi di SQL Server 2008. Berikut adalah contoh yang saya gunakan terhadap tabel kata kamus, jika saya ingin kata acak.

SELECT TOP 1
  word
FROM (
  SELECT TOP(@idx)
    word 
  FROM
    dbo.DictionaryAbridged WITH(NOLOCK)
  ORDER BY
    word DESC
) AS D
ORDER BY
  word ASC

Tentu saja, @idx adalah beberapa bilangan bulat yang dihasilkan secara acak yang berkisar dari 1 hingga COUNT (*) pada tabel target, secara inklusif. Jika kolom Anda diindeks, Anda juga akan mendapat manfaatnya. Keuntungan lain adalah Anda dapat menggunakannya dalam suatu fungsi, karena NEWID () tidak diizinkan.

Terakhir, kueri di atas berjalan sekitar 1/10 dari waktu exec dari NEWID () - jenis kueri pada tabel yang sama. YYMV.

alphadogg
sumber
1

Anda juga dapat mencoba menggunakan new id()fungsi.

Tulis saja kueri Anda dan gunakan urutan berdasarkan new id()fungsi. Ini cukup acak.

Jai - mendapat panggilan wawancara
sumber
1

Untuk MySQL untuk mendapatkan catatan acak

 SELECT name
  FROM random AS r1 JOIN
       (SELECT (RAND() *
                     (SELECT MAX(id)
                        FROM random)) AS id)
        AS r2
 WHERE r1.id >= r2.id
 ORDER BY r1.id ASC
 LIMIT 1

Lebih detail http://jan.kneschke.de/projects/mysql/order-by-rand/

Sophy
sumber
Setelah menguji banyak jawaban saya percaya bahwa ini adalah yang terbaik. Tampaknya cepat dan mengambil nomor acak yang bagus setiap kali. Tampaknya mirip dengan saran kedua @GreyPanther di atas, tetapi jawaban ini memilih lebih banyak angka acak.
Jeff Baker
1

Belum melihat variasi ini dalam jawaban. Saya memiliki kendala tambahan di mana saya perlu, diberikan benih awal, untuk memilih set baris yang sama setiap kali.

Untuk MS SQL:

Contoh minimum:

select top 10 percent *
from table_name
order by rand(checksum(*))

Waktu pelaksanaan normal: 1,00

Contoh NewId ():

select top 10 percent *
from table_name
order by newid()

Waktu pelaksanaan normal: 1.02

NewId()lebih lambat dari biasanya rand(checksum(*)), jadi Anda mungkin tidak ingin menggunakannya melawan set rekaman besar.

Pilihan dengan Benih Awal:

declare @seed int
set @seed = Year(getdate()) * month(getdate()) /* any other initial seed here */

select top 10 percent *
from table_name
order by rand(checksum(*) % seed) /* any other math function here */

Jika Anda perlu memilih set yang sama dengan seed, ini sepertinya berhasil.

klyd
sumber
1

Dalam MSSQL (diuji pada 11.0.5569) menggunakan

SELECT TOP 100 * FROM employee ORDER BY CRYPT_GEN_RANDOM(10)

secara signifikan lebih cepat daripada

SELECT TOP 100 * FROM employee ORDER BY NEWID()
David Knight
sumber
1

Dalam SQL Server Anda dapat menggabungkan TABLESAMPLE dengan NEWID () untuk mendapatkan keacakan yang cukup bagus dan masih memiliki kecepatan. Ini sangat berguna jika Anda benar-benar hanya menginginkan 1, atau sejumlah kecil, baris.

SELECT TOP 1 * FROM [table] 
TABLESAMPLE (500 ROWS) 
ORDER BY NEWID()
Chris Arbogast
sumber
1

Dengan SQL Server 2012+ Anda dapat menggunakan kueri FETCH OFFSET untuk melakukan ini untuk satu baris acak

select  * from MyTable ORDER BY id OFFSET n ROW FETCH NEXT 1 ROWS ONLY

di mana id adalah kolom identitas, dan n adalah baris yang Anda inginkan - dihitung sebagai angka acak antara 0 dan hitung () - 1 dari tabel (offset 0 adalah baris pertama setelah semua)

Ini berfungsi dengan lubang di data tabel, selama Anda memiliki indeks untuk bekerja dengan untuk klausa ORDER BY. Ini juga sangat baik untuk keacakan - saat Anda berusaha untuk lulus tetapi orang-orang cekatan dalam metode lain tidak ada. Selain itu kinerjanya cukup baik, pada dataset yang lebih kecil, ia bertahan dengan baik, meskipun saya belum mencoba tes kinerja serius terhadap beberapa juta baris.

gbjbaanb
sumber
0
 SELECT * FROM table ORDER BY RAND() LIMIT 1
Jeremy Ruten
sumber
Sepuluh tahun yang lalu (2005) beberapa pria mengatakan bahwa menggunakan ORDER BY RAND()itu salah ...
trejder
0

Saya harus setuju dengan CD-MAN: Menggunakan "ORDER BY RAND ()" akan bekerja dengan baik untuk tabel kecil atau ketika Anda melakukan SELECT Anda hanya beberapa kali.

Saya juga menggunakan teknik "num_value> = RAND () * ...", dan jika saya benar-benar ingin mendapatkan hasil acak, saya memiliki kolom "acak" khusus dalam tabel yang saya perbarui sekali sehari atau lebih. Proses UPDATE tunggal itu akan memakan waktu (terutama karena Anda harus memiliki indeks pada kolom itu), tetapi itu jauh lebih cepat daripada membuat angka acak untuk setiap baris setiap kali pilih dijalankan.

BlaM
sumber
0

Hati-hati karena TableSample tidak benar-benar mengembalikan sampel acak baris. Ini mengarahkan kueri Anda untuk melihat sampel acak dari halaman 8KB yang membentuk baris Anda. Kemudian, kueri Anda dieksekusi terhadap data yang terkandung di halaman ini. Karena cara data dapat dikelompokkan pada halaman ini (urutan penyisipan, dll), ini dapat menyebabkan data yang sebenarnya bukan sampel acak.

Lihat: http://www.mssqltips.com/tip.asp?tip=1308

Halaman MSDN ini untuk TableSample termasuk contoh cara menghasilkan sampel data acak yang sebenarnya.

http://msdn.microsoft.com/en-us/library/ms189108.aspx

Sean Turner
sumber
0

Tampaknya banyak ide yang terdaftar masih menggunakan pemesanan

Namun, jika Anda menggunakan tabel sementara, Anda dapat menetapkan indeks acak (seperti banyak solusi yang disarankan), dan kemudian ambil yang pertama yang lebih besar dari angka arbitrer antara 0 dan 1.

Misalnya (untuk DB2):

WITH TEMP AS (
SELECT COMLUMN, RAND() AS IDX FROM TABLE)
SELECT COLUMN FROM TABLE WHERE IDX > .5
FETCH FIRST 1 ROW ONLY
DAVID
sumber
2
Setelah mempertimbangkan solusi ini, saya telah menemukan cacat mendasar dalam logika saya. Ini akan secara konsisten mengembalikan nilai pengaturan kecil yang sama, di dekat bagian awal tabel, karena saya berasumsi bahwa jika ada distribusi rata antara 0 dan 1, ada kemungkinan 50% bahwa baris pertama akan memenuhi kriteria itu.
DAVID
0

Ada solusi yang lebih baik untuk Oracle daripada menggunakan dbms_random.value, sementara itu membutuhkan pemindaian penuh untuk memesan baris oleh dbms_random.value dan itu cukup lambat untuk tabel besar.

Gunakan ini sebagai gantinya:

SELECT *
FROM employee sample(1)
WHERE rownum=1
sev3ryn
sumber
0

Untuk Firebird:

Select FIRST 1 column from table ORDER BY RAND()
Luigi04
sumber
0

Untuk SQL Server 2005 dan di atas, memperluas jawaban @ GreyPanther untuk kasus-kasus ketika num_valuetidak memiliki nilai kontinu. Ini juga berfungsi untuk kasus-kasus ketika kita belum mendistribusikan dataset secara merata dan kapan num_valuebukan angka melainkan pengenal unik.

WITH CTE_Table (SelRow, num_value) 
AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY ID) AS SelRow, num_value FROM table
) 

SELECT * FROM table Where num_value = ( 
    SELECT TOP 1 num_value FROM CTE_Table  WHERE SelRow >= RAND() * (SELECT MAX(SelRow) FROM CTE_Table)
)
Endri
sumber
-1

Fungsi acak dari sql dapat membantu. Juga jika Anda ingin membatasi hanya satu baris, tambahkan saja pada akhirnya.

SELECT column FROM table
ORDER BY RAND()
LIMIT 1
nvnvashisth
sumber