Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Непонятное округление  [new]
Алексей200907
Guest
Добрый день!

Простите за "ламерский" вопрос, но не понимаю (MS SQL Server 2005):
declare @T table (F1 decimal(17,2), F2 decimal(17,2))
insert into @T values(1145.00, 3075.28)

select sum(F1)/sum(F2)
from @T

Дает совершенно неожиданный (для меня) результат:
---------------------------------------
0.372323

Почему произошло ОБРЕЗАНИЕ до 6 знаков??

(запрос специально упрощен для иллюстрации проблемы)
15 июл 09, 16:27    [7419907]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74927
BOL->Precision, Scale, and Length (Transact-SQL)
15 июл 09, 16:42    [7420066]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
Алексей2003
Member

Откуда: Москва
Сообщений: 5645
а сколько знаков надо то?

для спящего время бодрствования равносильно сну
15 июл 09, 16:42    [7420067]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
в дополнение к точности и длине - мои 5 коп:

Результат выраженияТип возвращаемых данных
категория decimal (p, s)decimal(38, s)
Взято отсюда: SUM (Transact-SQL)
15 июл 09, 16:51    [7420147]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
vino
Member

Откуда:
Сообщений: 1191
Алексей200907, с точными типами всегда спокойнее
declare @T table (F1 money, F2 money)
insert into @T values(1145.00, 3075.28)

select round(sum(F1)/sum(F2), 2)
from @T
15 июл 09, 16:56    [7420175]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
vino
Алексей200907, с точными типами всегда спокойнее
declare @T table (F1 money, F2 money)
insert into @T values(1145.00, 3075.28)

select round(sum(F1)/sum(F2), 2)
from @T
А DECIMAL - "неточный" тип что ли?
Вообще-то, MONEY - это DEC(19,4)
15 июл 09, 17:00    [7420205]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
Козьма Прутков
Member

Откуда: Москва
Сообщений: 186
Вообще и вправду интересный вопрос. Делаем так:
drop table testTable
go

declare @T table (F1 decimal(17,2), F2 decimal(17,2))
insert into @T values(1145.00, 3075.28)

select A=sum(F1), B=sum(F2), C=sum(F1)/sum(F2)
into testTable
from @T

exec sp_help 'testTable'

sp_help пишет следующее (часть колонок убрано):

Column_name Type Computed Length Prec Scale
A decimal no 17 38 2
B decimal no 17 38 2
C decimal no 17 38 6

Вот как объяснить расширение точности при делении с 2 до 6 знаков? В BOL пока ответа не нашел, видимо фича :)
------------
Чем сложнее решение задачи, тем больше вероятность, что оно неправильное
15 июл 09, 17:17    [7420299]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Точность, масштаб и длина (Transact-SQL)
15 июл 09, 17:25    [7420363]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74927
Козьма Прутков

Вот как объяснить расширение точности при делении с 2 до 6 знаков? В BOL пока ответа не нашел, видимо фича :)


Нет тут никакого расширения. Наоборот уменьшение scale идет, ибо:

при e1 / e2:

P = p1 - s1 + s2 + max(6, s1 + p2 + 1)
S = max(6, s1 + p2 + 1)

И:

The result precision and scale have an absolute maximum of 38. When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.
15 июл 09, 17:28    [7420392]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
Козьма Прутков
Member

Откуда: Москва
Сообщений: 186
Все, разобрался, pkarklin буквально во втором посте дал правильную ссылку. Минимальная точность при делении - 6 разрядов.
15 июл 09, 17:30    [7420402]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
Алексей200907
Guest
Чтобы не увлекаться цитированием отвечаю сразу :)
2) Надо - без округления (округлять будет клиент), я рассчитывал на результат, который получается без sum (0.37232382092037147836), но вопрос-то был:
а) почему вообще округляется
б) почему до 6 знаков
в) почему не округляется, а "обрезается"

3) decimal(38, s) - в моем случае s=2 - что это объясняет?
4) и 5) money тут вообще не причем (это ГКалл) :)

ну наконец 1), т.е. BOL:
The result precision and scale have an absolute maximum of 38. When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.

Т.е. видимо точность результата превысила 38??
Вот только непонятно, почему без sum все нормально? :(
15 июл 09, 17:31    [7420409]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
Алексей200907
почему без sum все нормально? :(
Паганель
Результат выраженияТип возвращаемых данных
категория decimal (p, s)decimal(38, s)
Взято отсюда: SUM (Transact-SQL)


Алексей200907
2) Надо - без округления (округлять будет клиент), я рассчитывал на результат, который получается без sum (0.37232382092037147836)
declare @T table (F1 decimal(17,2), F2 decimal(17,2))
insert into @T values(1145.00, 3075.28)

select cast(sum(F1) as decimal(17, 2))/cast(sum(F2) as decimal(17, 2))
from @T

---------------------------------------
0.37232382092037147836

(1 row(s) affected)
15 июл 09, 17:35    [7420442]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
Алексей200907
Guest
Паганель, вот теперь все стало на свои места!
Спасибо всем :)
15 июл 09, 17:38    [7420475]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
vino
Member

Откуда:
Сообщений: 1191
iap
vino
Алексей200907, с точными типами всегда спокойнее
declare @T table (F1 money, F2 money)
insert into @T values(1145.00, 3075.28)

select round(sum(F1)/sum(F2), 2)
from @T
А DECIMAL - "неточный" тип что ли?
Вообще-то, MONEY - это DEC(19,4)
Скорее MONEY - адекватный
Это абсолютно разные типы
declare @T table (F1 money, F2 money, F3 decimal(19,4), F4 decimal(19,4))
insert into @T values(1145.00, 3075.28, 1145.00, 3075.28)

select sum(F1)/sum(F2), sum(F3)/sum(F4)
from @T
15 июл 09, 18:06    [7420715]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
Алексей2003
Member

Откуда: Москва
Сообщений: 5645
2vino
почитайте про функцию sum, какой тип выдается на выходе. и все станет ясно.
а в целом money = decimal(19,4)

для спящего время бодрствования равносильно сну
15 июл 09, 19:07    [7420981]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
vino
Member

Откуда:
Сообщений: 1191
Алексей2003, так я ж о чем - есть тип, который правильно вычисляется всегда, я пока не встречал проблем с money
15 июл 09, 19:12    [7420998]     Ответить | Цитировать Сообщить модератору
 Re: Непонятное округление  [new]
daw
Member

Откуда: Муром -> Москва
Сообщений: 7381

> а в целом money = decimal(19,4)

таки нет. money - это money.
хранится он по-другому, правила приведения типов для него другие.

Posted via ActualForum NNTP Server 1.4

15 июл 09, 19:29    [7421050]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить