2013-08-26 1 views
5

Когда я исполняю этот SQLMSSQL - объединение всех с разной десятичной точностью

SELECT 1.4 UNION ALL 
SELECT 2.0400 union all 
SELECT 1.24 

я получаю следующий результат:

1,4000
2,0400
1,2400

Но когда я выполните следующий SQL:

SELECT sum(1.4) UNION ALL 
SELECT sum(2.0400) union all 
SELECT sum(1.24) 

я получаю следующий результат:

1,4
2,0
1,2

Почему существует разница в том, что точность (масштаб) применяется для всех записей? Не следует ли всегда использовать точность, когда данные не являются потерями, точно так же, как 1-й sql?

Thx.

ответ

0

Попробуйте это за такой же результат,

SELECT Cast(Sum(1.4) As Numeric(18,4)) UNION ALL 
SELECT Cast(Sum(2.0400) As Numeric(18,4)) union all 
SELECT Cast(Sum(1.24) As Numeric(18,4)) 
0

Попробуйте

SELECT sum(1.4)/1.0 UNION ALL 
SELECT sum(2.0400)/1.0 union all 
SELECT sum(1.24)/1.0 

ИЛИ

SELECT sum(1.4)/1.0 UNION ALL 
SELECT sum(2.0400) union all 
SELECT sum(1.24) 
0

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

SELECT sum(convert(decimal,1.4,3)) UNION ALL 
SELECT sum(2.0400) union all 
SELECT sum(1.24) 
0

Попробуйте этот запрос

SELECT convert(decimal(18,4),Sum(1.4)) UNION ALL 

SELECT convert(decimal(18,4),Sum(2.0400)) UNION ALL 

SELECT convert(decimal(18,4),Sum(1.24)) 
3

Я знаю, что это довольно старый вопрос, но ни один из существующих ответов не кажется, обратиться «почему?» аспект к вашему вопросу.

Во-первых, каков тип данных для ваших литералов? Я не был уверен (и не смотрел его), так что я побежал следующее:

select 1.4 union all 
select 'frob' 

который возвращает ошибку:

Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.

Итак, 1.4 и другие литералы numeric - aka decimal.

Далее, что тип возвращаемого значения функции SUM, если принят decimal(p,s) :

decimal(38, s)

Итак, типы данных 3 SUM выражений в запросе являются decimal(38,1), decimal(38,4) и decimal(38,2).Учитывая эти 3 типа данных, доступных для выбора, decimal(38,1) является окончательным выбранным типом, основанным на правилах для differing precisions and scales.

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.

Итак, наконец, вернуться к документации на decimal:

By default, SQL Server uses rounding when converting a number to a decimal or numeric value with a lower precision and scale. However, if the SET ARITHABORT option is ON, SQL Server raises an error when overflow occurs. Loss of only precision and scale is not sufficient to raise an error.

Так что это ваш конечный результат.


На первом таком типе может показаться удивительным, пока вы не поймете, что в целом, sum будет работать против нескольких строк, и это легко можно для нескольких значений заданной точности и масштаба, увлекают их собственный тип данных. decimal(38,s) дает максимально возможное пространство для размещения любых переполнений без потери точности при возникновении ошибки SUM() и означает, что окончательный тип данных может быть определен до выполнения запроса.