You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:15:08