Pregunta LINQ Usar Max () para seleccionar una sola fila


Estoy usando LINQ en un IQueryable devuelto por NHibernate y necesito seleccionar la fila con los valores máximos en un par de campos.

He simplificado el poco que me estoy quedando. Necesito seleccionar la fila de mi tabla con el valor máximo en un campo.

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

Esto es incorrecto pero no puedo encontrar la forma correcta.

Por cierto, lo que estoy tratando de lograr es aproximadamente esto:

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

Empecé con el lambda anterior pero he estado usando LINQPad para tratar de encontrar la sintaxis para seleccionar Max ().

ACTUALIZAR

La eliminación del GroupBy fue clave.

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


origen


Respuestas:


No veo por qué estás agrupando aquí.

Prueba esto:

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

Un enfoque alternativo que iteraría table solo una vez sería esto:

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

Esto es útil si table es un IEnumerable<T> que no está presente en la memoria o que se calcula sobre la marcha.


180
2018-02-02 15:30



Puede agrupar por estado y seleccionar una fila del grupo más grande:

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

El primero First() obtiene el primer grupo (el conjunto de filas con el estado más grande); el segundo First() obtiene la primera fila en ese grupo.
Si el estado es siempre independiente, puede reemplazar el segundo First() con Single().


12
2018-02-02 15:28



También puedes hacer:

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

10
2017-08-26 14:48



Al abordar la primera pregunta, si necesita tomar varias filas agrupadas por ciertos criterios con la otra columna con valor máximo, puede hacer algo como esto:

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



Simplemente en una línea:

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

Tenga en cuenta que hay dos acciones. la acción interna es para encontrar el valor máximo, la acción externa es para obtener el objeto deseado.


0
2017-11-13 12:25