考虑一个函数(GetData),它返回以下结果集,其中第一列是分区id,第二列是“TotalSales”:
DivisionID: 3 500
DivisionID: 3 500
DivisionID: 3 500
DivisionID: 4 800
DivisionID: 4 800
DivisionID: 5 50
我需要编写一个LINQ查询来获得以下结果:
DiviosnID 3: (500 * 3) - 500 = 1000
DiviosnID 4: (800 * 2) - 800 = 800
DiviosnID 5: 0 /*this since it's happening only once*/
所以总数变为:1000 + 800 = 1800
最后,此值应乘以-1,结果为-1800。
以下LINQ查询完成了工作,然而,它是IMSHO可怕的。问题是它是否可以重写以更快地执行并且看起来更好?!请注意那里有第三列,就像名为“TotalPurchases”的TotalSales一样,我需要对其进行相同的计算。
GetData()
.Where(t => t.DivisionId != 0)
.GroupBy(t => t.DivisionId)
.Where(g => g.Count() > 1)
.Select(g => new MyEntity
{
TotalSales = g.Sum(n => n.TotalSales) - (g.Sum(n => n.TotalSales) / g.Count()),
TotalPurchases = g.Sum(n => n.TotalPurchases) - (g.Sum(n => n.TotalPurchases) / g.Count())
})
.Union(Enumerable.Repeat(new MyEntity(), 1))
.Aggregate((t1, t2) => new MyEntity
{
TotalSales = -(t1.TotalSales + t2.TotalSales),
TotalPurchases = -(t1.TotalPurchases + t2.TotalPurchases),
});
谢谢
答案 0 :(得分:0)
快速首次尝试:
var consolidatedData = GetData()
.GroupBy(t => t.DivisionId)
.Where(g => g.Skip(1).Any(i => i.DivisionId != 0))
.Select(g => new
{
TotalSales = -(g.Sum(n => n.TotalSales) - g.Average(n => n.TotalSales)),
TotalPurchases = -(g.Sum(n => n.TotalPurchases) - g.Average(n => n.TotalPurchases))
});
var overallSales = consolidatedData.Sum(i => i.TotalSales);
var overallPurchases = consolidatedData.Sum(i => i.TotalPurchases);
使用Skip,您可以避免在每个组上运行可能很昂贵的Count() - 只需跳过一个项目,然后查看是否还有其他内容。
通过将结果构建到IEnumerable的anonyomous对象中,代码被简化了 - 然后您可以在想要最终总和时查询它。请注意,平均值也用于代替Sum / Count。
聚合被删除 - 您只需在需要时计算最终总和。
答案 1 :(得分:0)
我的主张:
var result = data
.Where(t => t.DivisionID != 0)
.GroupBy(t => t.DivisionID)
.Select(g => new MyEntity
{
TotalSales = g.Sum(n => n.TotalSales) - g.Average(n => n.TotalSales),
TotalPurchases = g.Sum(n => n.TotalPurchases) - g.Average(n => n.TotalPurchases)
})
.Aggregate(new MyEntity(), (t1, t2) => new MyEntity
{
TotalSales = t1.TotalSales - t2.TotalSales,
TotalPurchases = t1.TotalPurchases - t2.TotalPurchases,
});
不需要检查Where(g => g.Count() > 1)
,因为1个元素组的SUM和AVG相等,所以select将返回0。
我还删除了Union(Enumerable.Repeat(new MyEntity(), 1))
,我添加了seed
来汇总调用 - 这是起始值。
另一个:
var result = data
.Where(t => t.DivisionID != 0)
.GroupBy(t => t.DivisionID)
.Select(g => new MyEntity
{
TotalSales = g.Sum(n => n.TotalSales) - g.Average(n => n.TotalSales),
TotalPurchases = g.Sum(n => n.TotalPurchases) - g.Average(n => n.TotalPurchases)
})
.GroupBy(t => 0) // create single group
.Select(g => new MyEntity
{
TotalSales = -g.Sum(t => t.TotalSales),
TotalPurchases = -g.Sum(t => t.TotalPurchases)
})
.SingleOrDefault();
假设TotalSales
的{{1}}不变,您可以使用它:
DivisionId