【问题标题】:LINQ only sum rows if columns totaled is not zero如果总计的列不为零,则 LINQ 仅对行求和
【发布时间】:2018-01-26 01:50:56
【问题描述】:

给定以下行:

Amount, Name, Id
   Scenario 1: 100.00,ABC,101
              -100.00,ABC,101

   Scenario 2: 50.00,XYZ,123
              -100.00,XYZ,123

仅当金额总计未达到 0.00 时,我才想对行进行汇总和分组。所以 Linq 查询应该返回:

Amount, Name, Id
Scenario 1: 100.00,ABC,101
           -100.00,ABC,101

Scenario 2:-50.00,XYZ,123

到目前为止我所拥有的:

var results = dt.AsEnumerable().GroupBy(row => new
{
   Name = row.Field<string>("NAME"),
   Id = row.Field<int>("ID")
}).Select(grp =>
{
   DataRow dr = dt.NewRow();
   dr["AMOUNT"] = grp.Sum(r => r.Field<decimal>("AMOUNT"));
   dr["NAME"] = grp.Key.Name;
   dr["ID"] = grp.Key.Id;
   return dr;
}).CopyToDataTable();

【问题讨论】:

  • 我不知道你在问什么,你可能想编辑你的问题来尝试澄清你需要什么。
  • 你的例子对我来说是 0 意义
  • 只有“XYZ”不“总和”到0,所以我不确定为什么(根据我如何阅读你想要的)有两个“ABC”值显示在所需的输出(-100.0 + 100.0 == 0.0)。
  • 您要求根据分组求和的结果进行分组求和。这是一个三步过程 - 计算总数,保留大于 0 的那些,并为那些导致 0 的行添加行
  • 对不起,这些是我在记录中会遇到的不同情况。在场景 1 中:如果总金额加起来为零,则忽略总和。对于方案 2:如果总金额加起来不为零,则求和并分组行。

标签: c# linq


【解决方案1】:

您可以使用SelectMany 扩展方法尝试以下查询:

var query= dt.AsEnumerable().GroupBy(row => new
                             {
                                Name = row.Field<string>("NAME"),
                                Id = row.Field<int>("ID")
                             })
                            .SelectMany(grp=>
                             { 
                                var sum=grp.Sum(r => r.Field<decimal>("AMOUNT");
                                if(sum!=0)
                                {
                                   DataRow dr = dt.NewRow();
                                   dr["AMOUNT"] = sum;
                                   dr["NAME"] = grp.Key.Name;
                                   dr["ID"] = grp.Key.Id;
                                   return dr;
                                }
                                else
                                {
                                  return grp;
                                }
                             }).CopyToDataTable();  

【讨论】:

  • 不需要计算两次总和
【解决方案2】:

很难理解你在问什么,所以我假设你的意思是:

汇总和分组行,因此对于任何给定 ID,只列出一个汇总交易,除非总数为零,然后列出该 ID 的所有交易。

这是一个工作示例,带有您提供的测试数据:

var amounts = new[]
{
   new 
   {
       Amount = 100.00m,
       Name = "ABC",
       Id = 101,
   },
   new
   {
       Amount = -100.00m,
       Name = "ABC",
       Id = 101,
   },
   new
   {
       Amount = 50.00m,
       Name = "XYZ",
       Id = 123,
   },
   new
   {
       Amount = -100.00m,
       Name = "XYZ",
       Id = 123,
   },
};

// summarise everything
var summaries = from a in amounts
                group a by new { a.Id, a.Name } into grouping
                select new
                {
                    Amount = grouping.Sum(g => g.Amount),
                    grouping.Key.Name,
                    grouping.Key.Id,                    
                };

// get the ids of records we need the full audit log for
var zeroSummaries = summaries.Where(s => s.Amount == 0).Select(s => s.Id).ToList();

// concat the summarised records together with the ones we need the full audit log for
summaries = amounts.Where(a => zeroSummaries.Contains(a.Id))
                   .Concat(summaries.Where(s => s.Amount != 0));

这是输出:

【讨论】:

    猜你喜欢
    • 2017-11-11
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2021-07-20
    • 2022-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多