私の目標は、別のテーブルの主キーに基づいて、1 つのテーブルから加重平均を取得することです。
サンプルデータ:
表1
Key WEIGHTED_AVERAGE
0200 0
表2
ForeignKey Length Value
0200 105 52
0200 105 60
0200 105 54
0200 105 -1
0200 47 55
セグメントの長さに基づいて加重平均を取得し、-1 の値を無視する必要があります。SQL でこれを行う方法はわかっていますが、目標は LINQ でこれを行うことです。SQL では次のようになります。
SELECT Sum(t2.Value*t2.Length)/Sum(t2.Length) AS WEIGHTED_AVERAGE
FROM Table1 t1, Table2 t2
WHERE t2.Value <> -1
AND t2.ForeignKey = t1.Key;
私はまだ LINQ に不慣れなので、これをどのように変換すればよいかわかりません。結果の加重平均はおよそ 55.3 になるはずです。ありがとうございます。
ベストアンサー1
LINQ の拡張メソッドを次に示します。
public static double WeightedAverage<T>(this IEnumerable<T> records, Func<T, double> value, Func<T, double> weight)
{
if(records == null)
throw new ArgumentNullException(nameof(records), $"{nameof(records)} is null.");
int count = 0;
double valueSum = 0;
double weightSum = 0;
foreach (var record in records)
{
count++;
double recordWeight = weight(record);
valueSum += value(record) * recordWeight;
weightSum += recordWeight;
}
if (count == 0)
throw new ArgumentException($"{nameof(records)} is empty.");
if (count == 1)
return value(records.Single());
if (weightSum != 0)
return valueSum / weightSum;
else
throw new DivideByZeroException($"Division of {valueSum} by zero.");
}
これは、同じレコード内の別のフィールドに基づいて任意のデータ グループの加重平均を取得できるため、非常に便利になりました。
アップデート
ゼロ除算をチェックし、0 を返す代わりに、より詳細な例外をスローするようになりました。ユーザーが例外をキャッチし、必要に応じて処理できるようにします。