Używam LINQ na IQueryable zwrócony z NHibernate i muszę wybrać wiersz z maksymalną wartością (wartościami) w kilku polach.
Uprościłem kawałek, na którym się trzymam. Muszę wybrać jeden wiersz z mojej tabeli z maksymalną wartością w jednym polu.
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
To jest niepoprawne, ale nie mogę opracować odpowiedniej formy.
A tak przy okazji, to, co faktycznie próbuję osiągnąć, to mniej więcej to:
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();
Zacząłem od powyższej lambdy, ale używałem LINQPad do wypróbowania składni wyboru Max ().
AKTUALIZACJA
Usunięcie GroupBy było kluczowe.
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();
Odpowiedzi:
Nie rozumiem, dlaczego się tutaj grupujesz.
Spróbuj tego:
var maxValue = table.Max(x => x.Status) var result = table.First(x => x.Status == maxValue);
Alternatywnym podejściem, które można by powtórzyć
table
tylko raz, byłoby:var result = table.OrderByDescending(x => x.Status).First();
Jest to przydatne, jeśli
table
jest toIEnumerable<T>
, że nie jest obecny w pamięci lub że jest obliczana na bieżąco.źródło
from u in User_Accounts where u.Status == User_Accounts.Max(y => y.Status) select u
table.First(x => x.Status == table.Max(x => x.Status))
table
.Możesz też:
(from u in table orderby u.Status descending select u).Take(1);
źródło
Możesz grupować według stanu i wybrać wiersz z największej grupy:
Pierwsza
First()
pobiera pierwszą grupę (zestaw wierszy o największym statusie); drugaFirst()
otrzymuje pierwszy wiersz w tej grupie.Jeśli stan jest zawsze unqiue można zastąpić drugą
First()
zSingle()
.źródło
Odpowiadając na pierwsze pytanie, jeśli chcesz wziąć kilka wierszy pogrupowanych według określonych kryteriów z drugą kolumną o maksymalnej wartości, możesz zrobić coś takiego:
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;
źródło
Jeszcze jeden przykład:
Podążać:
qryAux = (from q in qryAux where q.OrdSeq == (from pp in Sessao.Query<NameTable>() where pp.FieldPk == q.FieldPk select pp.OrdSeq).Max() select q);
Równa się:
select t.* from nametable t where t.OrdSeq = (select max(t2.OrdSeq) from nametable t2 where t2.FieldPk= t.FieldPk)
źródło
Po prostu w jednej linii:
var result = table.First(x => x.Status == table.Max(y => y.Status));
Zauważ, że są dwie akcje. wewnętrzna akcja służy do znalezienia maksymalnej wartości, zewnętrzna akcja służy do uzyskania pożądanego obiektu.
źródło