Apa cara terbaik (dan tercepat) untuk mengambil baris acak menggunakan LINQ ke SQL ketika saya memiliki kondisi, misalnya beberapa bidang harus benar?
c#
.net
linq-to-sql
Julien Poulin
sumber
sumber
Jawaban:
Anda dapat melakukan ini di database, dengan menggunakan UDF palsu; di kelas parsial, tambahkan metode ke konteks data:
Kemudian hanya
order by ctx.Random()
; ini akan melakukan pengurutan acak di SQL-Server milikNEWID()
. yaituPerhatikan bahwa ini hanya cocok untuk tabel ukuran kecil hingga menengah; untuk tabel yang besar, ini akan berdampak pada kinerja server, dan akan lebih efisien untuk menemukan jumlah baris (
Count
), lalu memilih satu secara acak (Skip/First
).untuk pendekatan hitungan:
sumber
Contoh lain untuk Entity Framework:
Ini tidak bekerja dengan LINQ ke SQL. Itu
OrderBy
hanya dijatuhkan.sumber
EDIT: Saya baru saja menyadari ini LINQ ke SQL, bukan LINQ ke Objek. Gunakan kode Marc untuk mendapatkan database untuk melakukan ini untuk Anda. Saya meninggalkan jawaban ini di sini sebagai tempat menarik potensial untuk LINQ ke Objek.
Anehnya, Anda sebenarnya tidak perlu menghitungnya. Namun, Anda perlu mengambil setiap elemen kecuali Anda mendapatkan hitungannya.
Apa yang dapat Anda lakukan adalah mempertahankan gagasan tentang nilai "saat ini" dan jumlah saat ini. Saat Anda mengambil nilai berikutnya, ambil nomor acak dan ganti "saat ini" dengan "baru" dengan probabilitas 1 / n di mana n adalah hitungannya.
Jadi, saat Anda membaca nilai pertama, Anda selalu menjadikannya sebagai nilai "saat ini". Saat Anda membaca nilai kedua, Anda mungkin membuat nilai saat ini (probabilitas 1/2). Ketika Anda membaca nilai ketiga, Anda mungkin membuat nilai saat ini (probabilitas 1/3) dll. Ketika Anda kehabisan data, nilai saat ini adalah nilai acak dari semua yang Anda baca, dengan probabilitas seragam.
Untuk menerapkannya dengan syarat, abaikan saja apa pun yang tidak memenuhi syarat. Cara termudah untuk melakukannya adalah dengan hanya mempertimbangkan urutan "pencocokan" untuk memulai, dengan menerapkan klausa Where terlebih dahulu.
Berikut implementasi cepatnya. Saya pikir tidak apa-apa ...
sumber
current
akan selalu disetel ke elemen pertama. Pada iterasi kedua, ada perubahan 50% yang akan disetel ke elemen kedua. Pada iterasi ketiga, ada 33% kemungkinan itu akan disetel ke elemen ketiga. Menambahkan pernyataan break berarti Anda akan selalu keluar setelah membaca elemen pertama, membuatnya tidak acak sama sekali.Salah satu cara untuk mencapai secara efisien adalah dengan menambahkan kolom ke data Anda
Shuffle
yang diisi dengan int acak (karena setiap rekaman dibuat).Permintaan parsial untuk mengakses tabel secara acak adalah ...
Ini melakukan operasi XOR dalam database dan perintah berdasarkan hasil XOR tersebut.
Keuntungan:-
Ini adalah pendekatan yang digunakan oleh sistem otomasi rumah saya untuk mengacak daftar putar. Itu mengambil benih baru setiap hari memberikan urutan yang konsisten sepanjang hari (memungkinkan kemampuan jeda / melanjutkan yang mudah) tetapi tampilan baru di setiap daftar putar setiap hari baru.
sumber
result = result.OrderBy(s => s.Shuffle ^ seed);
(mis. Tidak perlu mengimplementasikan XOR melalui operator ~, & dan |).jika Anda ingin mendapatkan misalnya
var count = 16
baris acak dari tabel, Anda dapat menulisdi sini saya menggunakan EF, dan Tabel adalah Dbset
sumber
Jika tujuan mendapatkan baris acak adalah pengambilan sampel, saya telah berbicara sangat singkat di sini tentang pendekatan yang bagus dari Larson et al., Tim Riset Microsoft di mana mereka telah mengembangkan kerangka kerja pengambilan sampel untuk Server Sql menggunakan tampilan terwujud. Ada juga link ke kertas yang sebenarnya.
sumber
Penjelasan: Dengan memasukkan panduan (yang acak) urutan dengan orderby akan menjadi acak.
sumber
Datang ke sini bertanya-tanya bagaimana cara mendapatkan beberapa halaman acak dari sejumlah kecil, sehingga setiap pengguna mendapatkan 3 halaman acak yang berbeda.
Ini adalah solusi terakhir saya, mengerjakan kueri dengan LINQ terhadap daftar halaman di Sharepoint 2010. Ada dalam Visual Basic, maaf: p
Mungkin harus mendapatkan beberapa profil sebelum menanyakan sejumlah besar hasil, tetapi itu sempurna untuk tujuan saya
sumber
Saya memiliki kueri fungsi acak terhadap
DataTable
s:sumber
Contoh di bawah ini akan memanggil sumber untuk mengambil hitungan dan kemudian menerapkan ekspresi lewati pada sumber dengan angka antara 0 dan n. Metode kedua akan menerapkan urutan dengan menggunakan objek acak (yang akan mengurutkan semua yang ada di memori) dan memilih nomor yang diteruskan ke pemanggilan metode.
sumber
Saya menggunakan metode ini untuk mengambil berita acak dan berfungsi dengan baik;)
sumber
Menggunakan LINQ ke SQL di LINQPad sebagai pernyataan C # terlihat
SQL yang dihasilkan adalah
sumber
Jika Anda menggunakan LINQPad , alihkan ke mode program C # dan lakukan dengan cara ini:
sumber
Pilih 2 baris acak
sumber
Untuk menambah solusi Marc Gravell. Jika Anda tidak bekerja dengan kelas datacontext itu sendiri (karena Anda mem-proxy-nya misalnya untuk memalsukan datacontext untuk tujuan pengujian), Anda tidak dapat menggunakan UDF yang ditentukan secara langsung: itu tidak akan dikompilasi ke SQL karena Anda tidak menggunakannya dalam subclass atau kelas parsial dari kelas konteks data nyata Anda.
Solusi untuk masalah ini adalah dengan membuat fungsi Acak di proxy Anda, memberinya makan dengan kueri yang ingin Anda acak:
Berikut adalah cara Anda menggunakannya dalam kode Anda:
Untuk menjadi lengkap, berikut adalah cara mengimplementasikannya di datacontext FAKE (yang digunakan dalam entitas memori):
sumber