web-dev-qa-db-fra.com

LINQ Utilisation de Max () pour sélectionner une seule ligne

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();
88
Boggin

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.

210
Daniel Hilgarth

Vous pouvez aussi faire:

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

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().

13
SLaks

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;
7
Dmitry Komin

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)
0
SantanaFire