2013-08-26 13 views
5

Quando eseguo questo SQLMSSQL - UNION ALL con diversi precisione decimale

SELECT 1.4 UNION ALL 
SELECT 2.0400 union all 
SELECT 1.24 

ottengo il seguente risultato:

1,4000
2,0400
1,2400

Ma quando ho eseguire il seguente SQL

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

ottengo il seguente risultato:

1,4
2,0
1,2

Perché c'è una differenza in quello che di precisione (scala) viene applicata per tutti i record? Non dovrebbe sempre usare la precisione in cui nessun dato è in perdita, proprio come il 1 ° sql?

Thx.

risposta

0

Prova questo per lo stesso risultato,

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

Prova questo

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

O

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

normale query passando Valore stringa altrimenti utilizzando somma o decimale è stringa di convertire in specificata formattare questo è fatto

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

Prova questa ricerca

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

So che questo è abbastanza una vecchia questione, ma nessuna delle risposte esistenti sembrano affrontare il "perché?" aspetto alla tua domanda.

Innanzitutto, qual è il tipo di dati per le espressioni letterali? Non ero sicuro (e non guardare in su) così mi sono imbattuto il seguente:

select 1.4 union all 
select 'frob' 

che restituisce l'errore:

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

Okay, quindi 1.4 e gli altri letterali sono numeric - alias decimal.

Avanti, qual è il tipo di ritorno della funzione SUM, se superato un decimal(p,s) :

decimal(38, s)

Va bene, in modo che i tipi di dati delle 3 SUM espressioni nella query sono decimal(38,1), decimal(38,4) e decimal(38,2).Dati questi 3 tipi di dati disponibili, decimal(38,1) è il tipo scelto finale, in base alle regole per 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.

Così, finalmente, di nuovo alla documentazione su 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.

Ecco, questo è il risultato finale.


In un primo momento questo tipo può sembrare sorprendente, fino a quando ti rendi conto che in generale, sum opererà contro più righe ed è facilmente possibile per più valori di una data precisione e la scala a traboccare il proprio tipo di dati. decimal(38,s) offre lo spazio più ampio possibile per contenere eventuali overflow senza perdere precisione, per un particolare SUM() occorrenza e significa che il tipo di dati finale può essere deciso prima dell'esecuzione della query.