在 LINQ 中按聚合函数分组
Group by Aggregate functions in LINQ
我有一个以下类型的 SQL 查询,我试图使用 LINQ
在我的 C# 应用程序中获取数据
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 查询中的 date
和 scenario
作为执行函数的参数。
关于如何进行的任何想法或提示?
您可以使用 ?:
运算符来完成 CASE WHEN
部分。
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)
};
您有两个显而易见的选项:
- 在求和之前用
.Where()
子句过滤 grp
- 在
.Sum()
中测试 x.outcome 您的首选值
我认为前者更具可读性,而后者更符合您的 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),
});
我有一个以下类型的 SQL 查询,我试图使用 LINQ
在我的 C# 应用程序中获取数据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 查询中的 date
和 scenario
作为执行函数的参数。
关于如何进行的任何想法或提示?
您可以使用 ?:
运算符来完成 CASE WHEN
部分。
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)
};
您有两个显而易见的选项:
- 在求和之前用
.Where()
子句过滤 grp - 在
.Sum()
中测试 x.outcome 您的首选值
我认为前者更具可读性,而后者更符合您的 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),
});