Automatische Dezimalrundung

11

Die Frage ist relativ einfach. Ich muss 3 Spalten berechnen, in denen die mittleren Ergebnisse große Dezimalstellen sind, und ich habe schon früh ein Problem damit, dass SQL Server die Dezimalstellen unabhängig von der Umwandlung / Konvertierung im Grunde rundet.

Nehmen wir zum Beispiel eine einfache Unterteilung als 1234/1233 vor. Ein Taschenrechner erzeugt 1.00081103000811. Wenn ich dies auf SQL Server mache, erhalten wir Folgendes:

-- Result: rounded at 1.000811000... with trailing zeroes up until the 37 precision
SELECT CAST(CAST(1234 AS DEC(38,34))/CAST(1233 AS DEC(38,34)) AS DEC(38,37))

-- Result: rounded at 1.000811
SELECT CONVERT(DECIMAL(38,32), 1234)/CONVERT(DECIMAL(38,32),1233)

-- Correct result at 1,00081103000811
-- But this requires the zeroes to be put in manually when you don't
-- even know the precision of the end result
SELECT 1234.0/1233.00000000000000

Warum erfolgt diese automatische Rundung? Und was ist der beste Weg, um wahnsinnig lange Dezimalwerte zu berechnen, wenn Sie nicht sicher sind, wie groß eine Zahl (der Int- oder Dec-Teil) sein wird, da die Tabelle verschiedene Werte enthalten kann?

Vielen Dank!

Kahn
quelle

Antworten:

17

tl; dr

Berechnen Sie nicht in SQL

Länger

Die Ergebnisskala und -genauigkeit ist hier auf MSDN gut definiert . Es ist nicht wirklich intuitiv. In einfachen Worten geht jedoch die Genauigkeit verloren, wenn die Eingabeskalen hoch sind, da die Ergebnisskalen mit einem passenden Genauigkeitsabfall auf 38 gesenkt werden müssen.

Um Dinge zu bestätigen

  • Ihr zusätzliches CAST im ersten Beispiel fügt einfach Nullen hinzu
  • Das Abschneiden erfolgt gemäß meinem MSDN-Link (2. Beispiel)
  • Das dritte Beispiel mit Konstanten enthält Dezimalwerte, die gerade ausreichen (5,1) und 18,14).
    Dies bedeutet, dass die Ergebnisskala und die Genauigkeit nicht abgeschnitten werden (siehe Schlag).

Mehr zum 1. und 3. Fall ..

Die Ergebnisskala für eine Division lautet max(6, s1 + p2 + 1):

  • Das erste Beispiel ist 77, das auf 38 gesenkt wird. Die Präzision wird auf ähnliche Weise verringert, vorbehaltlich eines Minimums von 6 (siehe hier ).
  • Das dritte Beispiel ist 24, sodass die Genauigkeit nicht angepasst werden muss

Sie haben einige Optionen

  • Berechnen Sie im Client-Code zB .net
  • Verwenden Sie CLR-Funktionen, um .net-Berechnungen durchzuführen
  • lebe mit dem Verlust der Genauigkeit
  • Verwenden Sie float und leben Sie mit 15 signifikanten Zahlen als am besten

Schließlich finden Sie dies unter SO /programming/423925/t-sql-decimal-division-accuracy/424052#424052

gbn
quelle
1

Ich bin mir nicht sicher, ob dies hilft, aber für mich war meine temporäre Tabellenspalte auf dezimal gesetzt. Ich habe die Konvertierung (dezimal (15,2), 0,65) von der Einfügung in temp_table übergeben. Dies war eine automatische Rundung. Ich habe den Spaltentyp in eine Dezimalzahl (16,2) geändert, um der Übergabe zu entsprechen. In der Tabelle werden jetzt 0,65 gespeichert.

natur3
quelle
1

Ich musste herumarbeiten. Folgendes habe ich getan:

-----------------------------------
DECLARE @DENIED INT  = 33443
DECLARE @PAID INT = 148353
DECLARE @PCT Decimal (6,2)

SET @PCT = (@DENIED * 100.00 / @PAID)  -- Instead of dividing by 100, I included decimals

SELECT
@DENIED AS DEN
,@PAID AS PAID
,@PCT AS PCT

Ergebnisse:

DEN PAID    PCT
-----   ----    -----
33443   148353  22.54   -- Instead of 22.00

Hoffe das hilft.

Manoj C.
quelle