J'utilise LINQ sur un IQueryable renvoyé par NHibernate et je dois sélectionner la ligne avec la (les) valeur (s) maximale (s) dans plusieurs champs.
J'ai simplifié le bit que je colle. Je dois sélectionner la ligne de ma table avec la valeur maximale dans un champ.
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
Ceci est incorrect mais je ne peux pas trouver le bon formulaire.
BTW, ce que j'essaye réellement de réaliser est approximativement ceci:
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();
J'ai commencé avec le lambda ci-dessus, mais j'utilise LINQPad pour essayer de déterminer la syntaxe de sélection de Max ().
UPDATE
Supprimer le GroupBy était la clé.
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();
Je ne vois pas pourquoi vous regroupez ici.
Essaye ça:
var maxValue = table.Max(x => x.Status)
var result = table.First(x => x.Status == maxValue);
Une autre approche qui itérerait table
une seule fois serait la suivante:
var result = table.OrderByDescending(x => x.Status).First();
Ceci est utile si table
est un IEnumerable<T>
qui n'est pas présent dans la mémoire ou qui est calculé à la volée.
Vous pouvez aussi faire:
(from u in table
orderby u.Status descending
select u).Take(1);
Vous pouvez regrouper par statut et sélectionner une ligne du groupe le plus grand:
table.GroupBy(r => r.Status).OrderByDescending(g => g.Key).First().First();
Le premier First()
obtient le premier groupe (l'ensemble des lignes ayant le statut le plus grand); le second First()
obtient la première ligne de ce groupe.
Si le statut est toujours incorrect, vous pouvez remplacer le second First()
par Single()
.
Pour répondre à la première question, si vous devez prendre plusieurs lignes regroupées selon certains critères avec l’autre colonne de valeur maximale, vous pouvez procéder de la manière suivante:
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;
Plus un exemple:
Suivre:
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);
Équivaut à:
select t.* from nametable t where t.OrdSeq =
(select max(t2.OrdSeq) from nametable t2 where t2.FieldPk= t.FieldPk)