【问题标题】:Group by Aggregate functions in LINQ按 LINQ 中的聚合函数分组
【发布时间】:2017-01-12 14:14:53
【问题描述】:

我有一个以下类型的 SQL 查询,我试图在我的 C# 应用程序中使用 LINQ 获取数据

select 
sum(CASE when outcome = 0 then samplingweight else 0 end) tpcount, 
sum(CASE when outcome = 1 then samplingweight else 0 end) fpcount, 
sum(CASE when outcome = 2 then samplingweight else 0 end) mismatch, 
sum(CASE when outcome = 3 then samplingweight else 0 end) fncount, 
sum(CASE when outcome = 4 then samplingweight else 0 end) tncount, 
sum(samplingweight) totalweight, 
__date, 
scenario from MyTable
where __date = '30-Dec-16 12:00:00 AM' and scenario = 'parcels'
group by __date, scenario

注意:samplingweight 是 DB 中的双精度值。

我正在尝试并且能够达到以下状态

from pr in this.context.ComputedPrSet
where
    pr.Date.Equals(date) && pr.Scenario.Equals(scenario)
group pr by new { pr.Date, pr.Scenario }
into grp
select new
           {
               grp.Key.Date,
               grp.Key.Scenario,
               TruePositiveCount = grp.Sum(x => x.SamplingWeight) //I am stuck here. Not sure how to aggregate the properties 
           };

注意:上述 LINQ 查询中的datescenario 被作为参数传递给执行函数。

关于如何进行的任何想法或提示?

【问题讨论】:

  • grp.Where(x => x.outcome == 1).Sum(x => x.SamplingWeight)

标签: c# .net linq group-by aggregate


【解决方案1】:

您有两个容易看到的选项:

  • 在求和之前使用 .Where() 子句过滤 grp
  • 测试 x.outcome 在.Sum() 中的首选值

我认为前者更具可读性,而后者更符合您的 SQL。它们可能会以不同的方式转换为 SQL,具体取决于您的提供商。如果性能是一个问题,请务必评估生成的 SQL。

from pr in this.context.ComputedPrSet
where
    pr.Date.Equals(date) && pr.Scenario.Equals(scenario)
group pr by new { pr.Date, pr.Scenario }
into grp
select new
           {
               grp.Key.Date,
               grp.Key.Scenario,
               TruePositiveCount = grp.Where(x => x.outcome == 0).Sum(x => x.SamplingWeight),
               FPCount = grp.Sum(x => x.outcome == 1 ? x.SamplingWeight : 0),
           };

第三种选择是在数据库中按日期、场景和结果分组,然后在代码中将Select() 重新输入到您想要的对象中,如下所示:

this.Context.ComputedPrSet
    .Where(pr => pr.Date == date && pr.Scenario == scenario)
    .GroupBy(pr => new { pr.Date, pr.Scenario, pr.Outcome })
    .Select(grp => new {
        grp.Key.Date,
        grp.Key.Scenario,
        grp.Key.Outcome,
        Count = grp.Sum(pr => pr.SamplingWeight)
    })
    .AsEnumerable()
    // .AsEnumerable() will "close" the query in LINQ.
    // Further operations are done via LINQ to Objects after fetching the prior results from your DB
    .GroupBy(e => new { e.Date, e.Scenario })
    .Select(g => new {
        g.Key.Date,
        g.Key.Scenario,
        TruePositiveCount = g.FirstOrDefault(e => e.Outcome == 0),
        FPCount = g.FirstOrDefault(e => e.Outcome == 1),
    });

【讨论】:

    【解决方案2】:

    您可以使用?: 运算符来做@9​​87654322@ 部分。

    from pr in this.context.ComputedPrSet
    where
        pr.Date.Equals(date) && pr.Scenario.Equals(scenario)
    group pr by new { pr.Date, pr.Scenario }
    into grp
    select new
    {
        grp.Key.Date,
        grp.Key.Scenario,
        TruePositiveCount = grp.Sum(x => x.Outcome == 0?x.SamplingWeight:0)
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-11
      • 2012-11-02
      • 2012-02-09
      • 2012-10-27
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多