Hãy để tôi nói rõ nắm đấm: Tôi hoàn toàn hiểu rằng các loại dấu phẩy động không thể biểu diễn chính xác các giá trị thập phân . Đây không phải là về điều đó! Tuy nhiên, tính toán dấu phẩy động được cho là xác định .
Bây giờ điều này đã được thực hiện, hãy để tôi chỉ cho bạn thấy trường hợp tò mò mà tôi quan sát thấy ngày hôm nay. Tôi có một danh sách các giá trị dấu phẩy động và tôi muốn tổng hợp chúng:
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
Cho đến nay, rất tốt - không có bất ngờ ở đây. Chúng ta đều biết rằng 1.2
không thể được biểu diễn chính xác trong biểu diễn nhị phân, do đó, kết quả "không chính xác" được mong đợi.
Bây giờ điều kỳ lạ sau đây xảy ra khi tôi rời khỏi - tham gia một bảng khác:
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
( fiddle sql , bạn cũng có thể thấy kế hoạch thực hiện ở đó)
Tôi có cùng một tổng trên các giá trị giống nhau , nhưng một lỗi dấu phẩy động khác nhau . Nếu tôi thêm nhiều hàng vào bảng #A
, chúng ta có thể thấy rằng giá trị xen kẽ giữa hai giá trị đó. Tôi chỉ có thể tái tạo vấn đề này với một LEFT JOIN
; INNER JOIN
hoạt động như mong đợi ở đây.
Điều này là bất tiện, bởi vì nó có nghĩa là a DISTINCT
, GROUP BY
hoặc PIVOT
xem chúng là các giá trị khác nhau (đó thực sự là cách chúng tôi phát hiện ra vấn đề này).
Giải pháp rõ ràng là làm tròn giá trị, nhưng tôi tò mò: Có lời giải thích hợp lý nào cho hành vi này không?