Saran pertama Pradeep Adiga ORDER BY NEWID()
,, baik-baik saja dan sesuatu yang saya gunakan di masa lalu karena alasan ini.
Berhati-hatilah dengan menggunakan RAND()
- dalam banyak konteks hanya dieksekusi sekali per pernyataan sehingga tidak ORDER BY RAND()
akan berpengaruh (karena Anda mendapatkan hasil yang sama dari RAND () untuk setiap baris).
Contohnya:
SELECT display_name, RAND() FROM tr_person
mengembalikan setiap nama dari tabel orang kami dan nomor "acak", yang sama untuk setiap baris. Jumlahnya bervariasi setiap kali Anda menjalankan kueri, tetapi sama untuk setiap baris setiap kali.
Untuk menunjukkan bahwa sama halnya dengan RAND()
yang digunakan dalam ORDER BY
klausa, saya mencoba:
SELECT display_name FROM tr_person ORDER BY RAND(), display_name
Hasilnya masih dipesan dengan nama yang menunjukkan bahwa bidang pengurutan sebelumnya (yang diharapkan acak) tidak berpengaruh sehingga mungkin selalu memiliki nilai yang sama.
Memesan dengan NEWID()
tidak berfungsi, karena jika NEWID () tidak selalu dinilai ulang tujuan UUIDs akan rusak ketika memasukkan banyak baris baru dalam satu statemnt dengan pengidentifikasi unik sebagai kuncinya, jadi:
SELECT display_name FROM tr_person ORDER BY NEWID()
tidak memesan nama-nama "secara acak".
DBMS lainnya
Di atas berlaku untuk MSSQL (setidaknya 2005 dan 2008, dan jika saya ingat juga 2000). Fungsi mengembalikan UUID baru harus dievaluasi setiap kali di semua DBMS NEWID () berada di bawah MSSQL tetapi perlu memverifikasi ini dalam dokumentasi dan / atau dengan tes Anda sendiri. Perilaku fungsi hasil arbitrer lainnya, seperti RAND (), lebih cenderung bervariasi di antara DBMS, jadi sekali lagi periksa dokumentasi.
Saya juga melihat pemesanan dengan nilai-nilai UUID diabaikan dalam beberapa konteks karena DB mengasumsikan bahwa tipe tidak memiliki urutan yang berarti. Jika Anda menemukan ini adalah kasus yang secara eksplisit melemparkan UUID ke tipe string dalam klausa pemesanan, atau membungkus beberapa fungsi lain di sekitarnya seperti CHECKSUM()
di SQL Server (mungkin ada perbedaan kinerja yang kecil dari ini juga karena pemesanan akan dilakukan pada nilai 32-bit bukan 128-bit, meskipun apakah manfaatnya lebih besar daripada biaya menjalankan CHECKSUM()
per nilai, saya akan meninggalkan Anda untuk menguji).
Catatan Samping
Jika Anda menginginkan pemesanan yang sewenang-wenang tetapi agak dapat diulang, pesanlah dengan subset data yang relatif tidak terkontrol di baris itu sendiri. Misalnya salah satu atau ini akan mengembalikan nama dalam urutan yang sewenang-wenang tetapi berulang:
SELECT display_name FROM tr_person ORDER BY CHECKSUM(display_name), display_name -- order by the checksum of some of the row's data
SELECT display_name FROM tr_person ORDER BY SUBSTRING(display_name, LEN(display_name)/2, 128) -- order by part of the name field, but not in any an obviously recognisable order)
Pemesanan sewenang-wenang tetapi berulang tidak sering berguna dalam aplikasi, meskipun dapat berguna dalam pengujian jika Anda ingin menguji beberapa kode pada hasil dalam berbagai pesanan tetapi ingin dapat mengulangi setiap menjalankan dengan cara yang sama beberapa kali (untuk mendapatkan waktu rata-rata hasil lebih dari beberapa kali berjalan, atau pengujian bahwa perbaikan yang Anda lakukan pada kode tidak menghilangkan masalah atau ketidakefisienan yang sebelumnya disorot oleh inputet hasil tertentu, atau hanya untuk menguji bahwa kode Anda "stabil" yang mengembalikan hasil yang sama setiap kali jika mengirim data yang sama dalam urutan tertentu).
Trik ini juga dapat digunakan untuk mendapatkan hasil yang lebih sewenang-wenang dari fungsi, yang tidak memungkinkan panggilan non-deterministik seperti NEWID () di dalam tubuh mereka. Sekali lagi, ini bukan sesuatu yang mungkin sering berguna di dunia nyata tetapi bisa berguna jika Anda ingin fungsi mengembalikan sesuatu yang acak dan "acak-ish" cukup baik (tapi hati-hati mengingat aturan yang menentukan ketika fungsi yang ditentukan pengguna dievaluasi, yaitu biasanya hanya sekali per baris, atau hasil Anda mungkin tidak seperti yang Anda harapkan / butuhkan).
Performa
Seperti yang ditunjukkan EBarr, mungkin ada masalah kinerja dengan salah satu di atas. Untuk lebih dari beberapa baris Anda hampir dijamin untuk melihat output spooled ke tempdb sebelum jumlah baris yang diminta dibaca kembali dalam urutan yang benar, yang berarti bahwa bahkan jika Anda mencari 10 besar, Anda mungkin menemukan indeks lengkap pemindaian (atau lebih buruk, pemindaian tabel) terjadi bersamaan dengan blok penulisan yang sangat besar ke tempdb. Karenanya sangat penting, seperti halnya kebanyakan hal, untuk melakukan tolok ukur dengan data realistis sebelum menggunakan ini dalam produksi.