Row_number over (Partition by-xxx) in Linq?
Ich habe eine DataTable
der Struktur und Daten:
id | inst | name ------------------------ 1 | Gitarre | john 2 | guitar | george 3 | Gitarre | paul 4 | drums | ringo 5 | drums | pete
Kann ich abrufen der Datensätze wie diese:
IEnumerable <Beatle>...
class Beatle
{
int id;
string inst;
string name;
}
Ich mag würde, um die innere Ordnung von denen, die spielen die verschiedenen Instrumente. In MSSQL würde ich verwenden
SELECT
*
,Row_Number() OVER (PARTITION BY inst ORDER BY id) AS rn
FROM Beatles
Diese Abfrage gibt
id | inst | name | rn ----------------------------- 1 | Gitarre | Johannes | 1 2 | guitar | george | 2 3 | Gitarre | paul | 3 4 | drums | ringo | 1 5 | drums | pete | 2
Wie kann ich das machen, dass in Linq ?
Bearbeiten.(nach der akzeptierten Antworten)
Voll funktionsfähig-code :
var beatles = (new[] { new { id=1 , inst = "guitar" , name="john" },
new { id=2 , inst = "guitar" , name="george" },
new { id=3 , inst = "guitar" , name="paul" },
new { id=4 , inst = "drums" , name="ringo" },
new { id=5 , inst = "drums" , name="pete" }
});
var o = beatles.OrderBy(x => x.id).GroupBy(x => x.inst)
.Select(g => new { g, count = g.Count() })
.SelectMany(t => t.g.Select(b => b)
.Zip(Enumerable.Range(1, t.count), (j, i) => new { j.inst, j.name, rn = i }));
foreach (var i in o)
{
Console.WriteLine("{0} {1} {2}", i.inst, i.name, i.rn);
}
Linq2SQL oder EF? Nicht sicher, ob es einen Unterschied macht oder so 🙂
linq2objects.
Das sollte nicht zu schwer da die Select-überladung mit dem index-parameter auf, wenn ich das richtig verstehe.
linq2objects.
Das sollte nicht zu schwer da die Select-überladung mit dem index-parameter auf, wenn ich das richtig verstehe.
InformationsquelleAutor Royi Namir | 2012-04-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
B"H
Ich weiß, das ist alt. Aber warum ist nicht die Lösung einfach?
code
var o = beatles .GroupBy(x => x.inst) .SelectMany(g => g.OrderBy(x => x.name).Wählen Sie((j, i) => neue { j.inst, j.name, rn = i + 1 }));code
InformationsquelleAutor Rabbi
Versuchen Sie, diese one-liner:
Ausgabe:
.Select
statment. So hält sich die Anzahl der Gruppierung.Ich brach meinem Kopf, wie kommen
t
bekannt ist, nachselectmany
, dann merke ich, dass es nach derselect
und nicht nach derselectmany
. Bearbeitet für die Klarstellung. 🙂Ich bin neugierig, welche Art von SQL, die dies erzeugt, wenn EF unterstützt.
Seien Sie vorsichtig, auf der
.GroupBy
da .NET string-Vergleich ist case-Sensitiv ist, in der Erwägung, dass SQL nicht. Wenn Sieguitar
undGuitar
, erhalten Sie andere Ergebnisse als bei der im Vergleich zu SQL. Siehe dieser post SO für Optionen bei der Gruppierung strings: stackoverflow.com/questions/16190180/...das ist den meisten Linien die ich je gesehen habe in einem one-liner
InformationsquelleAutor Jon Comtois
Andere Idee ist eine Ansicht, wenn möglich.
InformationsquelleAutor leppie
Als @The_Smallest Punkte heraus, die Zeilennummer wird nicht unterstützt LINQ. Hier ist, wie können Sie bekommen, was Sie suchen, obwohl:
y => new { y.inst, y.name, rn = rns[y.inst]++ }
ist kein Ausdruck, das ist, warum es nicht kompiliert wird zum sql-Abfrage. Schade, aber, dass die Abfrage lokal ausgeführt werden, keine Vorteile von sql.Gut, können Sie ziehen Sie alle in den Speicher, wo es funktioniert. Siehe update oben.
Ja, wie du sagst, keine Vorteile von SQL. Wenn Sie wollen, zu nutzen, SQL, müssen Sie, wie @The_Smallest Punkte unten, erstellen eine gespeicherte Prozedur.
InformationsquelleAutor Ethan Brown
Andere Lösung für Linq to objects ist:
[ C# Demo ]
Ihre willkommen - HTH ;).
InformationsquelleAutor shA.t
Einige vielleicht nützlich finden in Ihren code ein, um den richtigen index
InformationsquelleAutor Tomasz Maj
Andere Lösung für das gleiche RANK() OVER (PARTITION BY "partitionBy" ORDER BY "orderBy" DESC):
InformationsquelleAutor Benjamin Fourgeaud