Consentitemi di esprimere il pugno ovvio: capisco perfettamente che i tipi in virgola mobile non possono rappresentare con precisione i valori decimali . Non si tratta di questo! Tuttavia, i calcoli in virgola mobile dovrebbero essere deterministici .
Ora che questo è fuori mano, lascia che ti mostri il caso curioso che ho osservato oggi. Ho un elenco di valori in virgola mobile e voglio riassumerli:
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
Fin qui tutto bene - nessuna sorpresa qui. Sappiamo tutti che 1.2non può essere rappresentato esattamente nella rappresentazione binaria, quindi ci si aspetta il risultato "impreciso".
Ora succede la seguente cosa strana quando mi unisco a sinistra per un altro tavolo:
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
( violino sql , puoi anche vedere il piano di esecuzione lì)
Ho la stessa somma sugli stessi valori, ma un diverso errore in virgola mobile. Se aggiungo più righe alla tabella #A, possiamo vedere che il valore si alterna tra questi due valori. Sono stato in grado di riprodurre questo problema solo con un LEFT JOIN; INNER JOINfunziona come previsto qui.
Questo è scomodo, perché significa che a DISTINCT, GROUP BYo PIVOTli vede come valori diversi (che è in realtà il modo in cui abbiamo scoperto questo problema).
La soluzione ovvia è arrotondare il valore, ma sono curioso: esiste una spiegazione logica per questo comportamento?