Функция ROUND против типа данных - PullRequest
1 голос
/ 05 марта 2020

Мой вопрос концептуален.

В приведенном ниже фрагменте кода я ожидаю получить точно такой же результат для всех "круглых" активаций.

Однако при использовании константы в качестве аргумента результат отличается от использования вычисленного или сохраненного значения.

В документации я не нашел ни одного комментария, который бы помог мне понять причину различия.

В ответ на подобное вопрос (sql серверная функция раунда не работает хорошо ), я был отослан к отличной статье https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html, но в следующем примере все случаи "float", поэтому Я не думаю, что есть причины для разных результатов.

-

DECLARE @value FLOAT;
SET @value = 4255.0;
CREATE TABLE TESTTABLE (
  FLOAT_VALUE FLOAT
)
INSERT INTO TESTTABLE(FLOAT_VALUE) VALUES (@value);
SELECT 0.015 * 4255.0 AS ORIGINAL_VALUE,
   ROUND(0.015 * 4255.0, 2) AS ROUND_FROM_CONSTANT, 
   ROUND(0.015 * CONVERT(FLOAT, 4255.0), 2) AS ROUND_FROM_CAST, 
   ROUND(0.015 * @value, 2) AS ROUND_FROM_VARIABLE,
   ROUND(0.015 * FLOAT_VALUE, 2) AS ROUND_FROM_FIELD
FROM TESTTABLE

1 Ответ

1 голос
/ 05 марта 2020

Причина, по которой вы получаете разные результаты, заключается в том, что в выражениях используются разные типы данных.

Как литерал, 4225.0 является decimal(5,1) , а не a float, поэтому, только когда вы явно приведете значение к плавающей точке, оно будет рассматриваться как единое целое. Поскольку float и decimal не работают одинаково, вы получаете разные результаты.

Мы будем go через каждое выражение:

  1. 0.015 * 4255.0

    Это оба значения decimal, a decimal(3,3) и decimal(5,1). Когда речь идет о различных масштабах, точностях и умножении, для их вычисления используется следующее:

    Precision = p1 + p2 + 1 Scale = s1 + s2

    Следовательно, в результате получается точность и масштаб 3+5+1 и 1+3 = decimal(9,4) Вот почему вы получаете результат 63.8250.

  2. ROUND(0.015 * 4255.0, 2)

    То же, что и выше, но затем вы округляете до 2 десятичных знаков; здесь нужно небольшое объяснение.

  3. ROUND(0.015 * CONVERT(float, 4255.0), 2)

    Здесь есть 2 типа данных: decimal(3,3) и float. Использование у нас есть 2 разных типа данных, приоритет имеет тип данных. Как 0.015 неявно приведен к float.

    CONVERT(float,0.015) * CONVERT(float, 4255.0) возвращает 63.825, однако, поскольку float является значением неточности, при использовании ROUND возвращается значение 63.82; потому что число на самом деле <<code>63.825 в неточном сохраненном значении (возможно, 63824999999999~).

  4. ROUND(0.015 * @value, 2)

    То же, что 3.

  5. ROUND(0.015 * FLOAT_VALUE, 2)

    То же, что и 3.

Ссылки:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...