Frage LINQ Verwenden Sie Max (), um eine einzelne Zeile auszuwählen


Ich verwende LINQ auf einem IQueryable, das von NHibernate zurückgegeben wird, und ich muss die Zeile mit dem maximalen Wert (den maximalen Werten) in einigen Feldern auswählen.

Ich habe das Teil, an dem ich festhalte, vereinfacht. Ich muss die eine Zeile aus meiner Tabelle mit dem maximalen Wert in einem Feld auswählen.

var table = new Table { new Row(id: 1, status: 10), new Row(id: 2, status: 20) }

from u in table
group u by 1 into g
where u.Status == g.Max(u => u.Status)
select u

Das ist falsch, aber ich kann nicht die richtige Form ausarbeiten.

BTW, was ich eigentlich versuche zu erreichen, ist ungefähr das:

var clientAddress = this.repository.GetAll()
    .GroupBy(a => a)
    .SelectMany(
            g =>
            g.Where(
                a =>
                a.Reference == clientReference && 
                a.Status == ClientStatus.Live && 
                a.AddressReference == g.Max(x => x.AddressReference) && 
                a.StartDate == g.Max(x => x.StartDate)))
    .SingleOrDefault();

Ich habe mit dem obigen Lambda angefangen, aber ich benutze LINQPad, um die Syntax für die Auswahl von Max () auszuarbeiten.

AKTUALISIEREN

Das Entfernen der GroupBy war der Schlüssel.

var all = this.repository.GetAll();

var address = all
            .Where(
                a =>
                a.Reference == clientReference && 
                a.Status == ClientStatus.Live && 
                a.StartDate == all.Max(x => x.StartDate) &&
                a.AddressReference == all.Max(x => x.AddressReference))
            .SingleOrDefault();

75
2018-02-02 15:22


Ursprung


Antworten:


Ich verstehe nicht, warum Sie hier gruppieren.

Versuche dies:

var maxValue = table.Max(x => x.Status)
var result = table.First(x => x.Status == maxValue);

Ein alternativer Ansatz, der iterieren würde table nur einmal wäre das:

var result = table.OrderByDescending(x => x.Status).First();

Dies ist hilfreich, wenn table ist ein IEnumerable<T> das ist nicht im Speicher vorhanden oder das wird im laufenden Betrieb berechnet.


180
2018-02-02 15:30



Sie können nach Status gruppieren und eine Zeile aus der größten Gruppe auswählen:

table.GroupBy(r => r.Status).OrderByDescending(g => g.Key).First().First();

Der Erste First() ruft die erste Gruppe ab (die Menge der Zeilen mit dem größten Status); der Zweite First() erhält die erste Zeile in dieser Gruppe.
Wenn der Status immer eindeutig ist, können Sie den zweiten ersetzen First() mit Single().


12
2018-02-02 15:28



Sie können auch Folgendes tun:

(from u in table
orderby u.Status descending
select u).Take(1);

10
2017-08-26 14:48



Wenn Sie die erste Frage angehen, können Sie, wenn Sie mehrere Zeilen nach bestimmten Kriterien mit der anderen Spalte mit maximalem Wert gruppieren müssen, Folgendes tun:

var query =
    from u1 in table
    join u2 in (
        from u in table
        group u by u.GroupId into g
        select new { GroupId = g.Key, MaxStatus = g.Max(x => x.Status) }
    ) on new { u1.GroupId, u1.Status } equals new { u2.GroupId, Status = u2.MaxStatus}
    select u1;

5
2017-11-10 19:38



Einfach in einer Zeile:

var result = table.First(x => x.Status == table.Max(y => y.Status));

Beachten Sie, dass es zwei Aktionen gibt. die innere Aktion ist für das Finden des maximalen Wertes, Die äußere Aktion ist für das gewünschte Objekt.


0
2017-11-13 12:25