明らかなこぶしを述べさせてください。浮動小数点型は10進数値を正確に表すことができないことを完全に理解しています。これはそれについてではありません!それにもかかわらず、浮動小数点計算は決定論的であることになっています。
これが邪魔にならないところで、今日私が観察した奇妙なケースを紹介しましょう。浮動小数点値のリストがあり、それらを合計したいと思います。
CREATE TABLE #someFloats (val float);
INSERT INTO #someFloats (val) VALUES (1), (1), (1.2), (1.2), (1.2), (3), (5);
SELECT STR(SUM(#someFloats.val), 30, 15) FROM #someFloats;
DROP TABLE #someFloats;
-- yields:
-- 13.600000000000001
これまでのところ、とても良いです-ここに驚きはありません。1.2
バイナリ表現で正確に表現できないことは誰でも知っているので、「不正確な」結果が予想されます。
ここで、別のテーブルを左結合すると、次の奇妙なことが起こります。
CREATE TABLE #A (a int);
INSERT INTO #A (a) VALUES (1), (2);
CREATE TABLE #someFloats (val float);
INSERT INTO #someFloats (val) VALUES (1), (1), (1.2), (1.2), (1.2), (3), (5);
SELECT #A.a, STR(SUM(#someFloats.val), 30, 15)
FROM #someFloats LEFT JOIN #A ON 1 = 1
GROUP BY #A.a;
DROP TABLE #someFloats;
DROP TABLE #A;
-- yields
-- 1 13.600000000000001
-- 2 13.599999999999998
(sql fiddle、そこに実行プランも表示されます)
私が持っている同じの総和と同じ値が、異なる浮動小数点エラーを。テーブル#A
に行を追加すると、値が2つの値の間で交互に表示されることがわかります。この問題を再現できたのはLEFT JOIN
; INNER JOIN
ここで期待どおりに動作します。
これはDISTINCT
、GROUP BY
またはPIVOT
を別の値と見なすことを意味するため、これは不便です(実際にこの問題を発見した方法です)。
明白な解決策は値を丸めることですが、私は興味があります:この動作について論理的な説明はありますか?