Значение усечения числового типа данных SQL?

Я действительно надеюсь, что какой-нибудь гуру SQL может помочь с этим (и мои извинения, если на этот вопрос уже был дан ответ. Я пытался найти аналогичный пост, но безрезультатно):

declare @theanswer numeric(38,16)

select @theanswer = 0.01 / 0.0074464347
select @theanswer

Вышеупомянутые результаты в 1.3429245542165000

но следующее (что выглядит одинаково для меня)

declare @val1 numeric(38,16);
declare @val2 numeric(38,16);

set @val1 = 0.01;
set @val2 = 0.0074464347;

select @val1/@val2

результаты с 1.342924 и обрезает его?

Любые идеи?


person Tom Miller    schedule 27.10.2011    source источник
comment
На Sql-Server 2008 я получил 1.3429245542165000   -  person sll    schedule 27.10.2011
comment
Попробуйте select @theanswer = CAST(0.01 as numeric(38,16)) / CAST(0.0074464347 AS numeric(38,16))   -  person sll    schedule 27.10.2011
comment
возможный дубликат Точность десятичного деления T-SQL   -  person Mikael Eriksson    schedule 27.10.2011
comment
stackoverflow.com/questions/5385326/   -  person Mikael Eriksson    schedule 27.10.2011
comment
выберите @val1/@val2 AS conv_factor   -  person Kip Real    schedule 27.10.2011


Ответы (1)


Чтобы получить реальную точность и масштаб результата (@val1/@val2), я бы выполнил этот скрипт T-SQL

DECLARE @val1 NUMERIC(38,16);
DECLARE @val2 NUMERIC(38,16);

SET @val1 = 0.01;
SET @val2 = 0.0074464347;

SELECT @val1/@val2
        ,SQL_VARIANT_PROPERTY(@val1/@val2, 'BaseType')  [BaseType]
        ,SQL_VARIANT_PROPERTY(@val1/@val2, 'Precision') [Precision]
        ,SQL_VARIANT_PROPERTY(@val1/@val2, 'Scale')     [Scale]

И результаты будут:

(No column name)    BaseType    Precision   Scale
1.342924            numeric         38          6

Таким образом, точность результата равна 38, а масштаб результата равен 6. В MSDN есть некоторые подробности относительно точности и масштаба арифметических операций. Эту информацию можно найти здесь: Точность, масштаб и длина (Transact-SQL)< /а>:

Operation = e1 / e2
Result precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Result scale * = max(6, s1 + p2 + 1)

Используя эти формулы, мы можем написать следующий скрипт T-SQL, чтобы получить теоретическую точность и масштаб результата (@val1/@val2):

SELECT   @p1 = 38   --or CONVERT(INT, SQL_VARIANT_PROPERTY(@val1, 'Precision'))
        ,@s1 = 16   --or CONVERT(INT, SQL_VARIANT_PROPERTY(@val1, 'Scale'))
        ,@p2 = 38   --or CONVERT(INT, SQL_VARIANT_PROPERTY(@val2, 'Precision'))
        ,@s2 = 16   --or CONVERT(INT, SQL_VARIANT_PROPERTY(@val2, 'Scale'));

--SELECT    @p1 [@p1], @s1 [@s1], @p2 [@p2], @s2 [@s2];

SELECT  @p_result = @p1 - @s1 + @s2 +   CASE 
                                            WHEN 6 >= @s1 + @p2 + 1 THEN 6 
                                            WHEN 6 < @s1 + @p2 + 1 THEN @s1 + @p2 + 1 
                                        END
        ,@s_result =    CASE 
                            WHEN 6 >= @s1 + @p2 + 1 THEN 6 
                            WHEN 6 < @s1 + @p2 + 1 THEN @s1 + @p2 + 1 
                        END;

SELECT  @p_result [@p_result], @s_result [@s_result];

Результат:

@p_result   @s_result
93          55

Итак, для этой арифметической операции (@val1/@val2) в theory точность и масштаб равны 93 и 55, но реальная точность и масштаб равны 38 и 6. Реальная точность равна 38, поскольку "точность результата и масштаб имеют абсолютный максимум 38".

Относительно реальной шкалы результатов (6) MSDN неясно: "Когда точность результата превышает 38, соответствующая шкала уменьшается, чтобы предотвратить усечение целой части результата" .

Чтобы увидеть, как «соответствующая шкала уменьшается», я выполнил приведенные выше тесты (сценарий 1 для реальной точности и масштаба и сценарий 2 для теоретической точности и масштаба), используя значения NUMERIC, имеющие одинаковую шкалу (16), но разные шкалы (от 16 до 38). ). Результаты этих испытаний таковы:

/*
Result prec. Result scale   (T=theoretical value, R=real value)
 T-R         T-R            --@val1 and @val2 data type
49-38       33-22           --NUMERIC(16, 16)
51-38       34-21           --NUMERIC(17, 16)
53-38       35-20           --NUMERIC(18, 16)
55-38       36-19           --NUMERIC(19, 16)
...
61-38       39-16           --NUMERIC(22, 16) -- <-- data type for [real] result scale 16
...                         
77-38       47-8            --NUMERIC(30, 16)
79-38       48-7            --NUMERIC(31, 16)
81-38       49-6            --NUMERIC(32, 16)
83-38       50-6            --NUMERIC(33, 16)
85-38       51-6            --NUMERIC(34, 16)
...
93-38       55-6            --NUMERIC(38, 16)
*/

Изучение этих результатов:

1.Я вижу арифметическую прогрессию по шкале реального результата: от 22 до 6, шаг -1.

2. Кроме того, если шкала для @val1 и @val2 постоянна (NUMERIC(...,16)), то существует обратная корреляция между точностью @val1 и @val2 (от 16 до 32) и шкалой [реального] результата (от 16 до 6).

3. Если точность @val1 и @val2 равна 32 или выше (NUMERIC(32->38,16)), [реальная] шкала результата всегда равна 6 => это ваш случай.

4. Если требуется большая [реальная] шкала результатов (более 6), вам нужно использовать более низкую точность для @val1 и @val2: NUMERIC(22, 16):

SELECT          
         CONVERT(NUMERIC(22,16),@val1) / CONVERT(NUMERIC(22,16),@val2) [CONVERT(NUMERIC(22,16)]
        ,SQL_VARIANT_PROPERTY( CONVERT(NUMERIC(22,16),@val1) / CONVERT(NUMERIC(22,16),@val2) , 'BaseType')  [BaseType]
        ,SQL_VARIANT_PROPERTY( CONVERT(NUMERIC(22,16),@val1) / CONVERT(NUMERIC(22,16),@val2) , 'Precision') [Precision]
        ,SQL_VARIANT_PROPERTY( CONVERT(NUMERIC(22,16),@val1) / CONVERT(NUMERIC(22,16),@val2) , 'Scale')     [Scale] 

CONVERT(NUMERIC(22,16) BaseType Precision Scale
---------------------- -------- --------- -----
1.3429245542165299     numeric  38        16
person Bogdan Sahlean    schedule 27.10.2011
comment
Отлично. Вы гений, и это очень ценно! - person Tom Miller; 27.10.2011
comment
Я просто энтузиаст SQL Server. Больше ничего. - person Bogdan Sahlean; 28.10.2011