LINQ to Entities中计算国家维度加权平均值的问题
按国家计算加权平均值的LINQ修正方案
问题背景
现有两张数据表:
Weight表
City Weight -------------------- Tokyo 100 München 150 Köln 200
Data表
ID Country City Value -------------------------------------------- 1 Germany München 10 2 Germany München 20 3 Japan Tokyo 12 4 Japan Tokyo 20 5 Japan Tokyo 8 6 Germany Köln 5 7 Germany Köln 7 8 Germany Köln 9
需求是按国家计算加权平均值,预期计算逻辑(以德国为例):
(10 * 150 + 20 * 150 + 5 * 200 + 7 * 200 + 9 * 200) / (150 + 150 + 200 + 200 + 200)
但原LINQ查询返回结果错误:
var MyResult = (from d in MyContext.Data join w in MyContext.Weight on d.City equals w.City select new { d.Country, d.City, d.Value, w.Weight }).GroupBy(p=>new {p.Country}) .Select(o=>new { o.Key.Country, WeightedAverage = o.Sum(k=>k.Value * k.Weight) / o.Sum(k=>k.Weight) })
问题原因与修正方案
核心问题
原查询的计算逻辑本身是正确的,但存在整数除法问题:由于Value和Weight都是整数类型,求和后的结果也是整数,直接相除会进行整数截断,导致结果丢失小数部分。比如德国的计算结果应为9.666...,但整数除法会返回9,与预期不符。
修正后的LINQ查询
将其中一个求和结果转换为浮点类型,确保运算为浮点数除法:
var MyResult = (from d in MyContext.Data join w in MyContext.Weight on d.City equals w.City select new { d.Country, d.Value, w.Weight }) .GroupBy(p => p.Country) .Select(o => new { Country = o.Key, WeightedAverage = o.Sum(k => (double)k.Value * k.Weight) / o.Sum(k => k.Weight) });
优化版本(可选)
如果数据量较大,可以先按城市分组计算中间值,再按国家汇总,减少分组运算的开销:
var MyResult = (from d in MyContext.Data join w in MyContext.Weight on d.City equals w.City group new { d.Value, w.Weight } by new { d.Country, d.City } into cityGroup select new { cityGroup.Key.Country, TotalValueWeight = cityGroup.Sum(k => k.Value * k.Weight), TotalWeight = cityGroup.Sum(k => k.Weight) }) .GroupBy(p => p.Country) .Select(o => new { Country = o.Key, WeightedAverage = o.Sum(k => (double)k.TotalValueWeight) / o.Sum(k => k.TotalWeight) });
验证结果
- 德国的加权平均值:
(10*150 + 20*150 +5*200 +7*200 +9*200)/(150*2 +200*3) = 8700/900 = 9.666... - 日本的加权平均值:
(12*100 +20*100 +8*100)/(100*3) = 4000/300 ≈13.333...
修正后的查询会返回包含小数部分的正确结果。
内容的提问来源于stack exchange,提问作者DooDoo
相关产品推荐
相关产品推荐

