Jaki jest najlepszy (i najszybszy) sposób na pobranie losowego wiersza za pomocą Linq do SQL, gdy mam warunek, np. Jakieś pole musi być prawdziwe?
c#
.net
linq-to-sql
Julien Poulin
źródło
źródło
Odpowiedzi:
Możesz to zrobić w bazie danych, używając fałszywego UDF; w klasie częściowej dodaj metodę do kontekstu danych:
Wtedy po prostu
order by ctx.Random()
; spowoduje to losowe uporządkowanie w SQL-Server dzięki uprzejmościNEWID()
. to znaczyZauważ, że jest to odpowiednie tylko dla małych i średnich tabel; w przypadku dużych tabel będzie to miało wpływ na wydajność serwera i efektywniejsze będzie znalezienie liczby wierszy (
Count
), a następnie wybranie jednego losowo (Skip/First
).dla podejścia liczącego:
źródło
Kolejny przykład dla Entity Framework:
To nie działa z LINQ to SQL.
OrderBy
Jest po prostu przed upadkiem.źródło
EDYCJA: Właśnie zauważyłem, że jest to LINQ to SQL, a nie LINQ to Objects. Użyj kodu Marca, aby uzyskać bazę danych, która zrobi to za Ciebie. Zostawiłem tę odpowiedź tutaj jako potencjalny punkt zainteresowania dla LINQ to Objects.
O dziwo, tak naprawdę nie musisz liczyć. Musisz jednak pobrać każdy element, chyba że otrzymasz liczbę.
Możesz zachować ideę „bieżącej” wartości i aktualnej liczby. Kiedy pobierasz następną wartość, weź liczbę losową i zamień „bieżącą” na „nową” z prawdopodobieństwem 1 / n, gdzie n jest liczbą.
Więc kiedy czytasz pierwszą wartość, zawsze ustawiasz ją jako „bieżącą”. Kiedy czytasz drugą wartość, możesz ustawić ją jako wartość bieżącą (prawdopodobieństwo 1/2). Kiedy czytasz trzecią wartość, możesz uznać, że jest to wartość bieżąca (prawdopodobieństwo 1/3) itd. Kiedy skończą się dane, bieżąca wartość jest losową spośród wszystkich, które czytasz, z jednakowym prawdopodobieństwem.
Aby zastosować to z warunkiem, po prostu zignoruj wszystko, co nie spełnia warunku. Najłatwiejszym sposobem na to jest rozważenie na początku tylko „pasującej” sekwencji, stosując najpierw klauzulę Where.
Oto szybka implementacja. Myślę, że to w porządku ...
źródło
current
będzie zawsze być ustawiony na pierwszym elemencie. W drugiej iteracji następuje 50% zmiana, że zostanie ustawiony na drugi element. W trzeciej iteracji istnieje 33% szansa, że zostanie ustawiony na trzeci element. Dodanie instrukcji break oznaczałoby, że zawsze wychodzisz po przeczytaniu pierwszego elementu, dzięki czemu nie jest on wcale przypadkowy.Jednym ze sposobów na efektywne osiągnięcie tego jest dodanie kolumny do danych
Shuffle
która jest wypełniona losową liczbą int (podczas tworzenia każdego rekordu).Częściowe zapytanie o dostęp do tabeli w kolejności losowej to ...
Wykonuje operację XOR w bazie danych i porządkuje wyniki tego XOR.
Zalety:-
To jest podejście używane przez mój system automatyki domowej do losowego tworzenia list odtwarzania. Każdego dnia wybiera nowe ziarno, zapewniając stałą kolejność w ciągu dnia (umożliwiając łatwe wstrzymywanie / wznawianie), ale każdego nowego dnia zapewnia świeże spojrzenie na każdą listę odtwarzania.
źródło
result = result.OrderBy(s => s.Shuffle ^ seed);
(tj. Nie ma potrzeby implementowania XOR za pośrednictwem operatorów ~, & i |).jeśli chcesz uzyskać np.
var count = 16
losowe wiersze z tabeli, możesz pisaćtutaj użyłem EF, a Table to Dbset
źródło
Jeśli celem pobierania losowych wierszy jest próbkowanie, omówiłem tutaj bardzo krótko o ładnym podejściu Larsona i in., Zespołu Microsoft Research, w którym opracowali ramy próbkowania dla Sql Server przy użyciu zmaterializowanych widoków. Jest też link do aktualnego artykułu.
źródło
Objaśnienie: Po wstawieniu guid (który jest losowy) kolejność z orderby będzie losowa.
źródło
Przyszedłem tutaj, zastanawiając się, jak uzyskać kilka losowych stron z niewielkiej liczby z nich, aby każdy użytkownik otrzymał różne losowe 3 strony.
To jest moje ostateczne rozwiązanie, pracujące z LINQ na liście stron w Sharepoint 2010. Jest w Visual Basic, przepraszam: p
Prawdopodobnie powinienem uzyskać pewne profilowanie przed zapytaniem o dużą liczbę wyników, ale jest to idealne do moich celów
źródło
Mam losowe zapytanie funkcji przeciwko
DataTable
s:źródło
Poniższy przykład wywoła źródło w celu pobrania liczby, a następnie zastosuje wyrażenie pomijania do źródła o liczbie od 0 do n. Druga metoda zastosuje kolejność przy użyciu losowego obiektu (który uporządkuje wszystko w pamięci) i wybierze liczbę przekazaną do wywołania metody.
źródło
używam tej metody do pobierania losowych wiadomości i działa dobrze;)
źródło
Używanie LINQ to SQL w LINQPad, jak wyglądają instrukcje C #
Wygenerowany kod SQL to
źródło
Jeśli używasz LINQPad , przełącz się do trybu programu C # i zrób w ten sposób:
źródło
Wybierz losowo 2 wiersze
źródło
Aby dodać do rozwiązania Marca Gravella. Jeśli nie pracujesz z samą klasą datacontext (ponieważ w jakiś sposób proxy ją proxy, np. Aby sfałszować kontekst danych do celów testowych), nie możesz bezpośrednio użyć zdefiniowanego UDF: nie zostanie on skompilowany do SQL, ponieważ nie używasz go w podklasa lub część klasy twojej prawdziwej klasy kontekstu danych.
Obejściem tego problemu jest utworzenie funkcji Randomize w serwerze proxy i przesłanie do niej zapytania, które ma być losowe:
Oto jak użyjesz go w swoim kodzie:
Aby być kompletnym, oto jak zaimplementować to w FAKE datacontext (który używa w jednostkach pamięci):
źródło