Ich habe in letzter Zeit nach LINQ
equivalent von WITH TIES
in sql server gesucht. Dabei bin ich auf einige Dinge gestoßen, die sich nicht als nützlich erweisen könnten.
Ich weiß diese Frage wurde schon einmal gestellt und hat eine akzeptierte Antwort, aber es funktioniert nicht den Weg mit Bindungen tut . Die Lösung, die GroupBy()
verwendet, führt nicht wie erwartet für TOP(3) WITH TIES
unter Berücksichtigung eines Datensatzes, der aus {3 2 2 1 1 0}
besteht. Die Ergebnismenge ist {3 2 2 1 1}
, wo sie {3 2 2}
Verwenden Sie die folgenden Beispieldaten (aus diese Frage) :
%Vor% Traditional OrderByDescending(p => p.Score).Take(3)
ergibt sich aus: Mamuzi , Kamala und einer von Tom ( oder Jerry ), wo BEIDE
Ich weiß, dass es kein eingebautes Äquivalent gibt und ich habe einen Weg gefunden, es zu implementieren. Ich weiß nicht, ob es der beste Weg ist, dies zu tun und sich für alternative Lösungen zu öffnen.
Bearbeiten:
@Zefnus
Ich war nicht sicher, in welcher Reihenfolge Sie es wollten, aber um die Reihenfolge zu ändern, können Sie eine OrderBy (s = & gt; s.Score) zwischen select i und ToList () setzen
Ich habe nicht die Möglichkeit zu überprüfen, welche SQL-Anweisung meine LINQ-Klausel erzeugen würde. Aber deine Antwort ist viel besser, denke ich. Und deine Frage war auch wirklich gut. Ich habe nie gedacht, dass ich in der Linq-Branche mithalten würde. ;)
Im Grunde genommen nimmt es nur die besten 3 Punkte von der ersten Liste und vergleicht sie mit der ganzen Liste und ich nehme nur die Punkte, die den Punkten der ersten Liste entsprechen.
IEnumerable<T>
nicht, wenn irgendetwas eine Datenbank berührt! Eine Lösung für LinqToSql und LinqToEntities sollte nicht IEnumerable<T>
. Ihre aktuelle Selbstantwort wird dazu führen, dass jede einzelne Person aus der Datenbank ausgewählt und dann im Speicher mithilfe von LinqToObjects
Um eine Lösung zu erstellen, die in SQL übersetzt und von der Datenbank ausgeführt wird, müssen Sie IQueryable<T>
und Ausdrücke statt.
Dies erstellt Abfragen des folgenden Formulars:
%Vor%Diese Abfrage ist nur etwa 50% schlechter als die Baseline-Abfrage :
%Vor%Bei einem Datensatz, der aus Ihren ursprünglichen 5 Datensätzen und weiteren 10000 Datensätzen besteht, die alle weniger als das Original aufweisen, sind beide mehr oder weniger unmittelbar (weniger als 20 Millisekunden).
Der IEnumerable<T>
Ansatz dauerte ganze 2 Minuten !
Wenn der Ausdruck "building" und "reflection" beängstigend wirkt, kann das gleiche mit einem Join erreicht werden:
%Vor%Mit der folgenden Abfrage als Ergebnis (mit ungefähr derselben Leistung):
%Vor% Eine andere Lösung - , die wahrscheinlich nicht so effizient ist wie die andere Lösung - ist TOP(3)
Scores zu erhalten und die Zeilen mit Score Werte, die in TOP(3)
enthalten sind.
Wir können Contains()
wie folgt verwenden:
Was an dieser Implementierung gut ist, ist die Erweiterungsmethode TopWithTies()
, die einfach implementiert werden kann;
Ich denke, dass Sie vielleicht etwas tun können wie:
%Vor%Zählen Sie die Anzahl der Vorkommen dieses Elements und dann:
%Vor%Ich denke, dass das vielleicht funktioniert;) Es ist nur eine Idee!
Ich habe eine Lösung gefunden, die den Score
-Feldwert der N
ten Zeile (in diesem Fall die 3. Zeile) mit .Skip(n-1).Take(1)
verwendet und alle Zeilen mit einem größeren oder gleichwertigen Wert wie folgt auswählt:
Tags und Links sql .net c# entity-framework linq