Problem z automatycznym zaokrąglaniem dziesiętnym

11

Pytanie jest stosunkowo proste. Muszę obliczyć 3 kolumny, w których średnie wyniki są ogromnymi miejscami po przecinku, i na początku mam problem z SQL Server, który zasadniczo zaokrągla liczby dziesiętne, niezależnie od rzutowania / konwersji.

Na przykład zróbmy prosty podział jako 1234/1233. Kalkulator wygeneruje 1 00081103000811. Ale kiedy robię to na SQL Server, otrzymujemy:

-- 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

Dlaczego występuje to automatyczne zaokrąglanie? A jaki jest najlepszy sposób obliczania niesamowicie długich wartości dziesiętnych, gdy nie możesz być pewien, jak duża będzie liczba (część int lub dec), ponieważ tabela może zawierać różne różne wartości?

Dzięki!

Kahn
źródło

Odpowiedzi:

17

tl; dr

Nie wykonuj obliczeń w języku SQL

Dłużej

Skala wyników i precyzja są dobrze zdefiniowane tutaj w MSDN . To naprawdę nie jest intuicyjne. Mówiąc prościej, precyzja jest tracona, gdy skale wejściowe są wysokie, ponieważ skale wyników należy upuścić do 38 z dopasowanym spadkiem precyzji.

Aby potwierdzić

  • Twój dodatkowy CAST w pierwszym przykładzie po prostu dodaje zera
  • Obcinanie odbywa się zgodnie z moim linkiem MSDN (drugi przykład)
  • Trzeci przykład ze stałymi implikuje wartości dziesiętne, które są wystarczające (5,1) i 18,14).
    Oznacza to, że skala wyników i precyzja nie są obcinane (patrz cios)

Więcej na temat 1. i 3. przypadku ..

Skala wyników dla podziału jest następująca max(6, s1 + p2 + 1):

  • Pierwszy przykład to 77, która jest zmniejszana do 38. Precyzja jest podobnie wymuszana, z zastrzeżeniem co najmniej 6 (zobacz to )
  • Trzeci przykład to 24, więc precyzja nie wymaga korekty

Masz kilka opcji

  • obliczyć w kodzie klienta np. .net
  • użyj funkcji CLR do wykonania obliczeń .net
  • żyć z utratą dokładności
  • użyj pływaka i żyj z 15 znaczącymi liczbami najlepiej

FInally, zobacz to na SO /programming/423925/t-sql-decimal-division-accuracy/424052#424052

gbn
źródło
1

Nie jestem pewien, czy to pomaga, ale dla mnie kolumna tabeli temp była ustawiona na dziesiętną, przekazywałam konwersję (dziesiętna (15,2), 0,65) ze wstawki do tabeli temp_table. To było automatyczne zaokrąglanie, zmieniłem typ kolumny na dziesiętny (16,2), aby dopasować to, co było przekazywane. Tabela przechowuje teraz 0,65.

natur3
źródło
1

Musiałem się obejść. Oto co zrobiłem:

-----------------------------------
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

Wyniki:

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

Mam nadzieję że to pomoże.

Manoj C.
źródło