Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Numeric(28,12) * integer  [new]
PavM
Member

Откуда:
Сообщений: 122
Всем доброго времени суток

Собственно вопрос достаточно простой, но поставил в тупик

DECLARE @Q NUMERIC (28, 12) = 0.637725819498
DECLARE @W INT = 1
SELECT @Q * @W, @Q * 1

Почему последние 2 цифры разные?
Таки нужно после умножения на 1, чтобы число осталось тем же. Как этого добиться?

Заранее спасибо!
15 ноя 12, 17:41    [13479742]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
SELECT @Q * @W, @Q * cast(1 as NUMERIC (28, 12) )


Сообщение было отредактировано: 15 ноя 12, 17:43
15 ноя 12, 17:42    [13479749]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
DECLARE @Q NUMERIC (28, 12) = 0.637725819498
DECLARE @W INT = 1
SELECT 
    sql_variant_property(@Q * @W, 'Scale')
    , sql_variant_property(@Q * @W, 'Precision')
    , sql_variant_property(@Q * 1, 'Scale')
    , sql_variant_property(@Q * 1, 'Precision')
15 ноя 12, 17:45    [13479765]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
Гавриленко Сергей Алексеевич
SELECT @Q * @W, @Q * cast(1 as NUMERIC (28, 12) )

Вернее,

SELECT @Q * @W, @Q * cast(1 as int )
15 ноя 12, 17:46    [13479771]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
PavM
Member

Откуда:
Сообщений: 122
Гавриленко Сергей Алексеевич
SELECT @Q * @W, @Q * cast(1 as NUMERIC (28, 12) )


А сами попробуйте так сделать :)

0.637726
15 ноя 12, 17:46    [13479774]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
PavM
Member

Откуда:
Сообщений: 122
Гавриленко Сергей Алексеевич
Гавриленко Сергей Алексеевич
SELECT @Q * @W, @Q * cast(1 as NUMERIC (28, 12) )

Вернее,

SELECT @Q * @W, @Q * cast(1 as int )


Опять меняет
0.63772581950
15 ноя 12, 17:47    [13479783]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
Вообще, да. Мне тоже интересно, почему отличается 1 и cast (1 as int), хотя 1 неявно конвертится к int.
DECLARE @Q NUMERIC (28, 12) = 0.637725819498
DECLARE @W INT = 1
SELECT @Q * @W, @Q * cast( 1 as int ), @q * 1 


SELECT 
    sql_variant_property(@Q * @W, 'Scale')
    , sql_variant_property(@Q * @W, 'Precision')
    , sql_variant_property(@Q * 1, 'Scale')
    , sql_variant_property(@Q * 1, 'Precision')
    , sql_variant_property(@Q * cast (1 as int), 'Scale')
    , sql_variant_property(@Q * cast (1 as int), 'Precision')    
    , sql_variant_property(1, 'BaseType')  
15 ноя 12, 17:50    [13479804]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
Microsoft SQL Server 2008 (SP3) - 10.0.5500.0 (X64) Sep 21 2011 22:45:45 Copyright (c) 1988-2008 Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.0 <X64> (Build 6002: Service Pack 2)

DECLARE @Q NUMERIC (28, 12) = 0.637725819498
DECLARE @W INT = 1

SELECT @Q * @W, @Q * cast(1 as int ), @Q * 1

SELECT 
    sql_variant_property(@Q * @W, 'Scale')
    , sql_variant_property(@Q * @W, 'Precision')
    , sql_variant_property(@Q * 1, 'Scale')
    , sql_variant_property(@Q * 1, 'Precision')
    , sql_variant_property(@Q * cast (1 as int), 'Scale')
    , sql_variant_property(@Q * cast (1 as int), 'Precision')    
    , sql_variant_property(1, 'BaseType')  


К сообщению приложен файл. Размер - 64Kb
15 ноя 12, 17:54    [13479832]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
PavM
Member

Откуда:
Сообщений: 122
Множитель (@W) приходит в виде параметра, и иногда он равен 1.
Поэтому просто @Q*1 я не могу использовать. только в явном виде или с конвертацией.
15 ноя 12, 17:55    [13479836]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
PavM
Member

Откуда:
Сообщений: 122
вариант с CASE тоже не катит

DECLARE @Q NUMERIC (28, 12) = 0.637725819498
DECLARE @W INT = 1
SELECT @Q * @W, @Q * cast( 1 as int ), @q * 1 , CASE WHEN @W = 1 THEN @Q * 1 ELSE @Q * @W END

0.63772581950 0.63772581950 0.637725819498 0.63772581950
15 ноя 12, 17:57    [13479846]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7381
DECLARE @Q NUMERIC (28, 12) = 0.637725819498
DECLARE @W numeric(1, 0) = 1
SELECT @Q * @W, sql_variant_property(@Q * @W, 'Precision'), sql_variant_property(@Q * @W, 'Scale')
, @Q * 1, sql_variant_property(@Q * 1, 'Precision'), sql_variant_property(@Q * 1, 'Scale')
select sql_variant_property(1, 'Precision')

вот так одинаково получается.
15 ноя 12, 17:59    [13479862]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
PavM
Member

Откуда:
Сообщений: 122
daw,

DECLARE @Q NUMERIC (28, 12) = 0.637725819498
DECLARE @W numeric(28, 0) = 10
SELECT @Q * @W, sql_variant_property(@Q * @W, 'Precision'), sql_variant_property(@Q * @W, 'Scale')
, @Q * 1, sql_variant_property(@Q * 1, 'Precision'), sql_variant_property(@Q * 1, 'Scale')
select sql_variant_property(1, 'Precision')

для отличного от 1 уже даёт не верный результат



подсказали вот такое решение:
SELECT @Q * @W, @Q * CAST(1 AS FLOAT), @Q * cast(1 as int )
15 ноя 12, 18:02    [13479898]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7381
а, ну и собственно, ссылка
http://msdn.microsoft.com/en-us/library/ms190476.aspx

если проверить Precision для int - то это 10. получаем результирующее: 28 + 10 + 1 = 39. соответственно, Scale обрезается на 1.
15 ноя 12, 18:03    [13479903]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
daw
а, ну и собственно, ссылка
http://msdn.microsoft.com/en-us/library/ms190476.aspx

если проверить Precision для int - то это 10. получаем результирующее: 28 + 10 + 1 = 39. соответственно, Scale обрезается на 1.
Нее. У меня вопрос, почему на выходе получаются разные типы данных при использовании "неявного" int и явного конверта к int.

Сообщение было отредактировано: 15 ноя 12, 18:04
15 ноя 12, 18:04    [13479916]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7381
> CAST(1 AS FLOAT)

если что-то точное хотите считать (типа денег), то лучше не надо.
15 ноя 12, 18:05    [13479924]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
PavM
Member

Откуда:
Сообщений: 122
daw
> CAST(1 AS FLOAT)

если что-то точное хотите считать (типа денег), то лучше не надо.


А почему, можно попобробнее?....

И если не это решение, то хотелось бы другие услышать :)
15 ноя 12, 18:08    [13479943]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7381
Гавриленко Сергей Алексеевич
Нее. У меня вопрос, почему на выходе получаются разные типы данных при использовании "неявного" int и явного конверта к int.


значит, для констант какие-то особые правила действуют при неявном преобразовании к numeric-у, когда выражения вычисляются. и преобразоваение идет к минимально возможному типу для этой конкретной константы. где-то я уже читал про это, но не найду сейчас. но не в документации, емнип.
15 ноя 12, 18:14    [13479976]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
PavM
Member

Откуда:
Сообщений: 122
PavM
вариант с CASE тоже не катит

DECLARE @Q NUMERIC (28, 12) = 0.637725819498
DECLARE @W INT = 1
SELECT @Q * @W, @Q * cast( 1 as int ), @q * 1 , CASE WHEN @W = 1 THEN @Q * 1 ELSE @Q * @W END



Тут я конечно натупил с кейсом. всё очень просто :)
DECLARE @Q NUMERIC (28, 12) = 0.637725819498
DECLARE @W INT = 1
SELECT @Q * @W, @Q * cast( 1 as int ), @q * 1 , CASE WHEN @W = 1 THEN @Q ELSE @Q * @W END


но для меня данный факт остался так и не понятым пока
15 ноя 12, 18:16    [13479984]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
Sekoka
Member

Откуда:
Сообщений: 73
Гавриленко Сергей Алексеевич
daw
а, ну и собственно, ссылка
http://msdn.microsoft.com/en-us/library/ms190476.aspx

если проверить Precision для int - то это 10. получаем результирующее: 28 + 10 + 1 = 39. соответственно, Scale обрезается на 1.
Нее. У меня вопрос, почему на выходе получаются разные типы данных при использовании "неявного" int и явного конверта к int.

Так как числу не указывают точность.
Константа 1 перобразуется в numeric(1,0), а переменая int в numeric(10,0).

Соответствено с контсантой нет переполнения, а с int - есть. Поэтому и усекается маштаб
16 ноя 12, 09:01    [13481743]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
PavM
Member

Откуда:
Сообщений: 122
daw
> CAST(1 AS FLOAT)

если что-то точное хотите считать (типа денег), то лучше не надо.


решение с case таки не работает

Считаем именно деньги. Почему лучше не использовать float?
всё еще ищу идеи для фикса :)
19 ноя 12, 15:19    [13495208]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
Crimean
Member

Откуда:
Сообщений: 13147
PavM
всё еще ищу идеи для фикса :)


все написано по той самой ссылке
http://msdn.microsoft.com/en-us/library/ms190476.aspx
или вдумчиво применять или уходить на стороннюю математическую либу, где "об этом" думать не надо будет
19 ноя 12, 15:29    [13495288]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
dalex1973
Member

Откуда: Польша
Сообщений: 287
PavM , Вам же ответ написали ответ "в неявном виде":

PrecisionOut=12,ScaleOut>28
Имеем PrecisionIn = (28+28)-38+1=19

DECLARE @Q NUMERIC (28, 12) = 0.637725819498
DECLARE @W decimal(28,19) = 100000
SELECT @Q * @W Value1, sql_variant_property(@Q * @W, 'Precision') Precision1 , sql_variant_property(@Q * @W, 'Scale') Scale1
, @Q * 1 Value2, sql_variant_property(@Q * 1, 'Precision') Precision2, sql_variant_property(@Q * 1, 'Scale') Scale2
select sql_variant_property(1, 'Precision')


Value1Precision1Scale1Value2Precision2Scale2
63772.58194980000038120.6377258194983012
19 ноя 12, 16:26    [13495657]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
PavM
Member

Откуда:
Сообщений: 122
dalex1973,

решение хорошее, но к сожалению тоже не подходит

DECLARE @Q NUMERIC(28, 12) = 12829282928292829.537229200000
DECLARE @W INT = 1
SELECT CAST(@Q * CAST(@W as NUMERIC(28, 19)) as NUMERIC(28, 12))

float тоже стало понятно почему
DECLARE @Q NUMERIC(28, 12) = 2829.537229200000
DECLARE @W INT = 1000
SELECT CAST(@Q * CAST(@W as float) as NUMERIC(28, 12))


виидмо придётся как-то логически разделять
20 ноя 12, 12:29    [13499436]     Ответить | Цитировать Сообщить модератору
 Re: Numeric(28,12) * integer  [new]
dalex1973
Member

Откуда: Польша
Сообщений: 287
А так:

DECLARE @Q NUMERIC(28, 12) = 1282928292829.537229
DECLARE @W INT = 1000

SELECT CAST(@Q * @W AS NUMERIC(30, 12)) Value1
	,sql_variant_property(CAST(@Q * @W AS NUMERIC(30, 12)), 'Precision') Precision1
	,sql_variant_property(CAST(@Q * @W AS NUMERIC(30, 12)), 'Scale') Scale1
	,@Q * 1000 Value2
	,sql_variant_property(@Q * 1000, 'Precision') Precision2
	,sql_variant_property(@Q * 1000, 'Scale') Scale2
20 ноя 12, 15:22    [13501031]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить