Was ist der beste (und schnellste) Weg, um eine zufällige Zeile mit Linq to SQL abzurufen, wenn ich eine Bedingung habe, z. B. muss ein Feld wahr sein?
c#
.net
linq-to-sql
Julien Poulin
quelle
quelle
Antworten:
Sie können dies in der Datenbank tun, indem Sie eine gefälschte UDF verwenden. Fügen Sie in einer Teilklasse dem Datenkontext eine Methode hinzu:
Dann einfach
order by ctx.Random()
; Dies führt eine zufällige Bestellung auf dem SQL-Server mit freundlicher Genehmigung vonNEWID()
. dhBeachten Sie, dass dies nur für kleine bis mittelgroße Tische geeignet ist. Bei großen Tabellen wirkt sich dies auf die Leistung des Servers aus, und es ist effizienter, die Anzahl der Zeilen zu ermitteln (
Count
) und dann eine zufällig auszuwählen (Skip/First
).für den Zählansatz:
quelle
Ein weiteres Beispiel für Entity Framework:
Dies funktioniert nicht mit LINQ to SQL. Das
OrderBy
wird einfach fallen gelassen.quelle
EDIT: Ich habe gerade erst bemerkt, dass dies LINQ to SQL ist, nicht LINQ to Objects. Verwenden Sie Marc's Code, um die Datenbank dazu zu bringen, dies für Sie zu tun. Ich habe diese Antwort hier als potenziellen Punkt von Interesse für LINQ to Objects hinterlassen.
Seltsamerweise müssen Sie nicht wirklich zählen. Sie müssen jedoch jedes Element abrufen, es sei denn, Sie erhalten die Anzahl.
Was Sie tun können, ist die Idee eines "aktuellen" Werts und der aktuellen Anzahl beizubehalten. Wenn Sie den nächsten Wert abrufen, nehmen Sie eine Zufallszahl und ersetzen Sie die "aktuelle" durch "neue" mit einer Wahrscheinlichkeit von 1 / n, wobei n die Anzahl ist.
Wenn Sie also den ersten Wert lesen, machen Sie diesen immer zum "aktuellen" Wert. Wenn Sie den zweiten Wert lesen, Sie könnten , dass der aktuelle Wert (Wahrscheinlichkeit 1/2) machen. Wenn Sie den dritten Wert zu lesen, Sie können machen , dass der aktuelle Wert (Wahrscheinlichkeit 1/3) usw. Wenn Sie von Daten abgelaufen haben, ist der aktuelle Wert ein gelegentlich man aus allen denen , die Sie mit einheitlicher Wahrscheinlichkeit lesen.
Um dies mit einer Bedingung anzuwenden, ignorieren Sie einfach alles, was die Bedingung nicht erfüllt. Der einfachste Weg, dies zu tun, besteht darin, zunächst nur die "übereinstimmende" Sequenz zu berücksichtigen, indem Sie zuerst eine Where-Klausel anwenden.
Hier ist eine schnelle Implementierung. Ich denke es ist okay ...
quelle
current
Wird bei der ersten Iteration immer auf das erste Element gesetzt. Bei der zweiten Iteration wird eine Änderung von 50% vorgenommen, die auf das zweite Element gesetzt wird. Bei der dritten Iteration besteht eine Wahrscheinlichkeit von 33%, dass das dritte Element verwendet wird. Das Hinzufügen einer break-Anweisung würde bedeuten, dass Sie nach dem Lesen des ersten Elements immer beenden, sodass es überhaupt nicht zufällig ist.Eine Möglichkeit, dies effizient zu erreichen, besteht darin, Ihren Daten eine Spalte hinzuzufügen
Shuffle
, die mit einem zufälligen int gefüllt ist (während jeder Datensatz erstellt wird).Die Teilabfrage für den Zugriff auf die Tabelle in zufälliger Reihenfolge lautet ...
Dies führt eine XOR-Operation in der Datenbank durch und ordnet nach den Ergebnissen dieses XOR.
Vorteile: -
Dies ist der Ansatz, den mein Hausautomationssystem verwendet, um Wiedergabelisten nach dem Zufallsprinzip zu sortieren. Es wählt jeden Tag einen neuen Startwert aus und gibt tagsüber eine einheitliche Reihenfolge (was einfache Pausen- / Wiederaufnahmefunktionen ermöglicht), aber jeden neuen Tag einen neuen Blick auf jede Wiedergabeliste.
quelle
result = result.OrderBy(s => s.Shuffle ^ seed);
(dh das XOR muss nicht über die Operatoren ~, & und | implementiert werden).Wenn Sie zB
var count = 16
zufällige Zeilen aus der Tabelle erhalten möchten , können Sie schreibenhier habe ich EF verwendet, und die Tabelle ist ein Dbset
quelle
Wenn der Zweck des Erhaltens Zufallsreihen abtastet, ich habe sehr kurz gesprochen hier über einen netten Ansatz von Larson et al., Microsoft Research Team , in dem sie einen Stichprobenrahmen für SQL Server materialisierte Ansichten entwickelt haben. Es gibt auch einen Link zum eigentlichen Artikel.
quelle
Erläuterung: Durch Einfügen der Guid (die zufällig ist) wäre die Reihenfolge mit orderby zufällig.
quelle
Kam hierher und fragte mich, wie man ein paar zufällige Seiten von einer kleinen Anzahl von ihnen bekommt, so dass jeder Benutzer einige andere zufällige 3 Seiten bekommt.
Dies ist meine endgültige Lösung, bei der ich mit LINQ eine Liste von Seiten in Sharepoint 2010 abfrage. Es ist in Visual Basic, sorry: p
Wahrscheinlich sollte ein Profil erstellt werden, bevor eine große Anzahl von Ergebnissen abgefragt wird, aber es ist perfekt für meinen Zweck
quelle
Ich habe zufällige Funktionsabfrage gegen
DataTable
s:quelle
Im folgenden Beispiel wird die Quelle aufgerufen, um eine Zählung abzurufen, und anschließend ein Sprungausdruck auf die Quelle mit einer Zahl zwischen 0 und n angewendet. Die zweite Methode wendet die Reihenfolge unter Verwendung des zufälligen Objekts an (das alles im Speicher ordnet) und wählt die Nummer aus, die an den Methodenaufruf übergeben wird.
quelle
Ich benutze diese Methode für zufällige Nachrichten und ihre Arbeit gut;)
quelle
Die Verwendung von LINQ to SQL in LINQPad als C # -Anweisungen sieht folgendermaßen aus
Das generierte SQL ist
quelle
Wenn Sie LINQPad verwenden , wechseln Sie in den C # -Programmmodus und gehen Sie folgendermaßen vor:
quelle
Wählen Sie zufällige 2 Zeilen
quelle
Zur Lösung von Marc Gravell hinzufügen. Wenn Sie nicht mit der Datenkontextklasse selbst arbeiten (weil Sie sie irgendwie als Proxy verwenden, z. B. um den Datenkontext zu Testzwecken zu fälschen), können Sie die definierte UDF nicht direkt verwenden: Sie wird nicht in SQL kompiliert, da Sie sie nicht in a verwenden Unterklasse oder Teilklasse Ihrer realen Datenkontextklasse.
Eine Problemumgehung für dieses Problem besteht darin, eine Zufallsfunktion in Ihrem Proxy zu erstellen und diese mit der Abfrage zu versorgen, die Sie zufällig auswählen möchten:
So würden Sie es in Ihrem Code verwenden:
Um vollständig zu sein, wird dies folgendermaßen im FAKE-Datenkontext implementiert (der in Speicherentitäten verwendet wird):
quelle