Автоматическое десятичное округление


11

Вопрос относительно прост. Мне нужно вычислить 3 столбца, где средние результаты - огромные десятичные дроби, и я сталкиваюсь с проблемой на ранних этапах, когда SQL Server в основном округляет десятичные числа независимо от каких-либо приведений / преобразований.

Например, давайте сделаем простое деление как 1234/1233. Калькулятор выдаст 1 00081103000811. Но когда я делаю это на SQL Server, мы получаем следующее:

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

Почему происходит автоматическое округление? И как лучше всего рассчитать безумно длинные десятичные значения, когда вы не можете быть уверены, насколько большим будет число (часть int или dec), поскольку таблица может содержать различные значения?

Спасибо!

Ответы:


17

ТЛ; др

Не делайте вычисления на языке SQL

дольше

Масштаб и точность результата хорошо определены здесь, в MSDN . Это не интуитивно понятно. Однако, проще говоря, точность теряется, когда входные весы высоки, потому что весы результата должны быть уменьшены до 38 с соответствующим падением точности.

Чтобы подтвердить вещи

  • Ваш дополнительный CAST в первом примере просто добавляет нули
  • Усечение происходит согласно моей ссылке MSDN (2-й пример)
  • В третьем примере с константами подразумеваются десятичные значения, которых достаточно (5,1) и 18,14).
    Это означает, что масштаб и точность результата не имеют усечения (см. Удар)

Подробнее о 1-м и 3-м случаях.

Шкала результата для подразделения max(6, s1 + p2 + 1):

  • Первый пример, это 77, которое упало до 38. Точность снижается аналогичным образом, с минимумом 6 (см. Это )
  • Третий пример, это 24, поэтому точность не нуждается в настройке

У вас есть несколько вариантов

  • рассчитать в коде клиента, например .net
  • использовать функции CLR для расчетов .net
  • жить с потерей точности
  • используйте float и живите с 15 значащими фигурами как лучше

Наконец, посмотрите это на SO /programming/423925/t-sql-decimal-division-accuracy/424052#424052


1

Не уверен, что это поможет, но для меня столбец временной таблицы был установлен в десятичном формате, я передавал преобразование (десятичное (15,2), 0,65) из вставки в temp_table. Это было автоматическое округление, я изменил тип столбца на десятичный (16,2), чтобы соответствовать тому, что было передано. Таблица сейчас хранит 0,65.


1

Я должен был сделать работу вокруг. Вот что я сделал:

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

Результаты:

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

Надеюсь это поможет.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.