LINQ基于最新日期的条目总和

时间:2014-09-24 11:24:04

标签: c# linq linq-to-sql

我有一张这样的表:

Code | BuildDate  | BuildQuantity
---------------------------------
1    | 2013-04-10 | 4
1    | 2014-09-23 | 1
1    | 2014-08-20 | 2
7    | 2014-02-05 | 4

我希望LINQ查询获取每个代码的最新构建日期,为该代码选择BuildQuantity,依此类推所有记录,并总结它。因此,对于上述数据,结果应为1 + 4 = 5

这就是我正在尝试的:

var built = (from tb in db.Builds
             orderby tb.BuildDate descending
             group tb by tb.Code into tbgrp
             select tbgrp.Sum(c => c.BuildQuantity)).First();

此查询返回7 ...我做错了什么?

2 个答案:

答案 0 :(得分:8)

在你拿第一个代码之前,你总结了所有代码的BuildQuantities,而不是你想要的第一个。

int built = db.Builds
    .GroupBy(b => b.Code)
    .Sum(g => g.OrderByDescending(b => b.BuildDate).First().BuildQuantity); 

答案 1 :(得分:3)

您正在寻找每个代码的最后一个条目的构建数量的总和。您目前在分组之前订购,实际上并没有做任何事情(在分组之后,订单未定义)

首先,您希望通过代码获取最新元素。让小组先。通过扩展方法写作更加舒服:

IGrouping<int, Build> grouped = db.Builds.GroupBy(tb => tb.Code)

我们现在将元素分组。从每个组中,我们希望得到按生成日期降序排序的第一个元素。

var firsts = grouped.Select(gr => gr.OrderByDescending(gr => gr.BuildDate)
                                    .First())

最后,我们可以得到总和:

var sum = firsts.Sum(tb => tb.BuildQuantity);

将这一切插入一起变成

var sum = db.Builds.GroupBy(tb => tb.Code).
          .Select(gr => gr.OrderByDescending(gr => gr.BuildDate).First())
          .Sum(tb => tb.BuildQuantity);

分组依据具有重载功能,允许您滚动组中的几乎所有内容。

如果您喜欢紧凑型代码,可以编写

var sum = db.Builds
          .GroupBy(tb => tb.Code,
                   tb => tb,
                   gr => gr.OrderByDescending(gr => gr.BuildDate)
                           .First()
                           .BuildQuantity)
          .Sum()

虽然我不会从可读性的角度推荐它