LINQ使用Max()选择单行


95

我在NHibernate返回的IQueryable上使用LINQ,我需要在几个字段中选择具有最大值的行。

我简化了我坚持的内容。我需要从我的表中选择一行,并在一个字段中取最大值。

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

这是不正确的,但我无法制定正确的表格。

顺便说一句,我实际上想实现的目标大致是:

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

我从上面的lambda开始,但是我一直在使用LINQPad尝试找出选择Max()的语法。

更新

删除GroupBy是关键。

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


@ M.Babcock在这个问题上有一个很好的答案:stackoverflow.com/a/6330485/444244
Boggin 2012年

有比这更好的了……
M.Babcock


@Serge我同意morelinq是最好的,但是我担心这个项目会妨碍添加新库。
博金

Answers:


230

我不明白您为什么在这里分组。

试试这个:

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

table仅迭代一次的另一种方法是:

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

这是有益的,如果table是的IEnumerable<T>是内存中不存在或者是实时计算。


1
我取出了分组,发现可以正常工作: from u in User_Accounts where u.Status == User_Accounts.Max(y => y.Status) select u
Boggin

1
您还可以嵌套lambda语法: table.First(x => x.Status == table.Max(x => x.Status))
Landon Poch 2012年

13
@LandonPoch:这不是一个好主意,因为这将计算最多N次,其中N为中的项目数table
丹尼尔·希尔加斯

2
@Daniel Hilgarth:好收获!实际上,这将计算表中每行的最大值。我的错。
兰登·波奇


13

您可以按状态分组,并从最大的分组中选择一行:

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

第一个First()获得第一组(状态最大的行集);第二个First()获得该组中的第一行。
如果状态总是unqiue,可以更换第二First()Single()


7

解决第一个问题,如果您需要按照特定条件将几行与另一列具有最大值的行合并,则可以执行以下操作:

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;

0

再举一个例子:

跟随:

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

等于:

 select t.*   from nametable t  where t.OrdSeq =
        (select max(t2.OrdSeq) from nametable t2 where t2.FieldPk= t.FieldPk)

-1

只需一行:

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

注意,有两个动作。内部动作用于找到最大值,外部动作用于获取所需的对象。


在对已接受答案的评论中讨论了该方法,并指出这是一个坏主意。
博金
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.