Please consider this tables:
Weight:
City Weight
--------------------
Tokyo 100
München 150
Köln 200
and 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
I want to calculate Weighted Average for each Country:
I wrote this query:
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)
})
But it returns wrong Weighted Average for me. I want to calculate this formula:
For Germany:
(10 * 150 + 20 * 150 + 5 * 200 + 7 * 200 + 9 * 200) / (150 + 150 + 200 + 200 + 200)
How can I achieve my desire result ?
Thanks
Since you have very your data denormalized in very peculiar way one way to handle it would be by creating a subquery which will create the
Country->SUM(Weight)"mapping". For example (since SQL Sever does not seem to havefirstaggregate function I substitute it here withmaxwhich will not work correctly in cases when some data is missing inWeighttable):Sample db fiddle - https://www.db-fiddle.com/f/fg1rXi5gTPjcGv7MS35TGB/1 . Output:
Not sure that this is possible to rewrite in form of EF Core LINQ query but you can try to do it in parts (i.e. one for fetching dictionary and another to fetch weighted sum -
sum(d.Value * w.Weight)) and perform final join in memory.