none
Problema Somma e Conversione RRS feed

  • Domanda

  • Ciao a tutti,

    Ho un problema che mi sta facendo diventare pazzo, ho questi valori che escono da una tabella.

    824,24176
    824,24176
    824,24176
    875,32316
    1295,53996
    1193,37716
    875,32316
    1144,9944
    902,30956
    1049,48182

    Se faccio la somma manuale e la conversione select cast(sum((824.24176+824.24176+824.24176+875.32316+1295.53996+1193.37716+875.32316+1144.99440+902.30956+1049.48182)) as decimal(18,3)) mi viene il seguente risultato : 9809.075

    Se faccio la somma dalla tabella e poi la conversione , mi viene questo risultato 9809.074

    Da cosa dipende...

    No riesco a capire e mi falliscono alcuni controlli.

    Grazie

    Simone

    giovedì 11 aprile 2013 13:04

Risposte

  • E' una questione di arrotondamento e troncamento credo (:

    prova a castare a DECIMAL(18,4) e vedrai che il risultato è 9809.0745,  probabilmente se eseguita in un modo viene fatto il calcolo e vengono troncate le cifre decimali a 3, mentre nel secondo caso viene effettuato un arrotondamento implicito (che trasforma il dato in .... ,075).

    Ipotesi


    • Modificato _ Luca Gaspari giovedì 11 aprile 2013 13:42
    • Contrassegnato come risposta Irina Turcu martedì 30 aprile 2013 12:45
    giovedì 11 aprile 2013 13:24
  • Ciao Simone,

    Mi dispiace per la mia risposta, il mio italiano non è abbastanza buono;

    if you work with floatingpoints, then you always work with an approximation of a number, never an exact number. Even 0 could differ from 0 with floatingpoints.
    Every calculation that you make with floatingpoints, increases the inaccuracy in the result.
    For your problem here, first convert to exact numbers (decimal), then do the calculations, and do them only on using the converted ones.

    SUM

    (CASE

    WHEN col2 In ('BDK','CHA','GPU')

    THEN cast(col1 as decimal(18,3))

    ELSE 0

    END ) AS imp    


    Regards, Nico

    pdfaid, my blog

    • Contrassegnato come risposta Irina Turcu martedì 30 aprile 2013 12:44
    venerdì 12 aprile 2013 17:39
  • Ciao a tutti,

    Se può interessare, l'unico modo per affrontare questo problema è inserire l'opzione MAXDOP 1

    Spiegano anche il motivio.

    http://sqlserver-online.blogspot.it/2010/02/did-you-know-aggregate-functions-on.html

    Grazie Ciao

    Simone

    • Contrassegnato come risposta Irina Turcu martedì 30 aprile 2013 12:44
    sabato 13 aprile 2013 15:28

Tutte le risposte

  • E' una questione di arrotondamento e troncamento credo (:

    prova a castare a DECIMAL(18,4) e vedrai che il risultato è 9809.0745,  probabilmente se eseguita in un modo viene fatto il calcolo e vengono troncate le cifre decimali a 3, mentre nel secondo caso viene effettuato un arrotondamento implicito (che trasforma il dato in .... ,075).

    Ipotesi


    • Modificato _ Luca Gaspari giovedì 11 aprile 2013 13:42
    • Contrassegnato come risposta Irina Turcu martedì 30 aprile 2013 12:45
    giovedì 11 aprile 2013 13:24
  • Ciao,

    Nada non funziona..

    Ti spiego cosa faccio.

    CTE_1 (data tabella 1 con filtri)

    CTE_2 (CTE_1 aggregata e cast a decimal)

    CTE_3 (TABELLA DI CONFRONTO)

    se faccio un confronto massivo tramite except mi da questo record perchè trova il valore 9809,075 mentre nella tabella di confronto c'è 9809,074.

    se faccio il confrono solo su questo record mi funziona tutto 9809,074  tabella di confronto c'è 9809,074.

    come è possibile secondo voi


    giovedì 11 aprile 2013 13:46
  • Puoi postare le tue query per farci capire meglio? Perché spiegata così, mi viene da risponderti esattamente come prima.

    giovedì 11 aprile 2013 14:55
  • Ecco l'esempio


    1 - Esempio con risulato = 6101.141

    create table a (
        
        col1  FLOAT,
        COL2  char(9)
        
        )
        
        truncate table a
        insert into a  select  cast(2033.7135 as float) ,'BDK'
        insert into a  select   cast(2033.7135 as float) ,'BDK'
        insert into a  select   cast(2033.7135 as float) ,'BDK'
        
        
        SELECT
        CAST((SUM(CASE WHEN col2 In ('BDK','CHA','GPU') THEN col1 ELSE 0 END )) AS DECIMAL(18,3)) AS imp    
        FROM  a
       

    2 - esempio con risultato  con risulato = 6101.140

    In questo caso prendo i dati da un'altra tabella che ha dentro questi valori, ma il risultato cambia.

     SELECT
        CAST((SUM(CASE WHEN col2 In ('BDK','CHA','GPU') THEN imp2 ELSE 0 END )) AS DECIMAL(18,3)) AS imp    
        FROM  a

    La colonna è configurata così




    • Modificato SimoneN venerdì 12 aprile 2013 08:26 Mancavano le immagini
    venerdì 12 aprile 2013 08:14
  • Non so se hai sbagliato a scriverla ora o l'hai presa col copia-incolla dal tuo codice ma nell'esempio 2 stai sommando imp2 mentre nell'esempio1 sommi col1.. 

    Per avere l'esempio completo, posta anche la struttura e le insert di dati della tabella dell'esempio2.

    Continuo a pensare che sia una questione di precisione del tipo e di arrotondamenti automatici.

    DECLARE @Table TABLE 
    (
        
        Column1 FLOAT,
        Column2 char(9)
    )
      
    INSERT INTO @Table SELECT CAST(2033.7135 AS FLOAT) ,'BDK'
    INSERT INTO @Table SELECT CAST(2033.7135 AS FLOAT) ,'BDK'
    INSERT INTO @Table SELECT CAST(2033.7135 AS FLOAT) ,'BDK'
        
    SELECT 
    	SUM(Column1) AS Importo_Float,
    	CAST(SUM(Column1) AS DECIMAL(18,3)) AS Importo_Decimal_18_3,
    	CAST(SUM(Column1) AS DECIMAL(18,4)) AS Importo_Decimal_18_4
    FROM @Table
    ;

    venerdì 12 aprile 2013 08:50
  • Ecco ho trovato il problema...

    http://support.microsoft.com/kb/976041/it

    ne sapete qualcosa voi ?

    Ciao

    venerdì 12 aprile 2013 09:35
  • Secondo me non centra molto quel fix col tuo problema, se però hai trovato il problema testalo pure e sappici dire (:

    Ciao

    venerdì 12 aprile 2013 10:28
  • Eccomi,

    Non capisco, ma questo MAXdop mi cambia i risulati.

    Come è possibile

    venerdì 12 aprile 2013 12:35
  • Puoi per cortesia postare la struttura della seconda tabella da dove leggi i dati?

    Grazie.

    venerdì 12 aprile 2013 13:16
  • Ciao Luca ,

    il problema è come dici tu, sulle conversioni.

    Ma non so come risolvere il problema , o letto che i float  ogni volta possono dare un risultato diverso .

    il problema è che nella tabella ho tutti float.

    Non so come procedere.

    Grazie

    Ciao

    Simone

    venerdì 12 aprile 2013 17:09
  • Ciao Simone,

    Mi dispiace per la mia risposta, il mio italiano non è abbastanza buono;

    if you work with floatingpoints, then you always work with an approximation of a number, never an exact number. Even 0 could differ from 0 with floatingpoints.
    Every calculation that you make with floatingpoints, increases the inaccuracy in the result.
    For your problem here, first convert to exact numbers (decimal), then do the calculations, and do them only on using the converted ones.

    SUM

    (CASE

    WHEN col2 In ('BDK','CHA','GPU')

    THEN cast(col1 as decimal(18,3))

    ELSE 0

    END ) AS imp    


    Regards, Nico

    pdfaid, my blog

    • Contrassegnato come risposta Irina Turcu martedì 30 aprile 2013 12:44
    venerdì 12 aprile 2013 17:39
  • Ciao a tutti,

    Se può interessare, l'unico modo per affrontare questo problema è inserire l'opzione MAXDOP 1

    Spiegano anche il motivio.

    http://sqlserver-online.blogspot.it/2010/02/did-you-know-aggregate-functions-on.html

    Grazie Ciao

    Simone

    • Contrassegnato come risposta Irina Turcu martedì 30 aprile 2013 12:44
    sabato 13 aprile 2013 15:28
  • Ciao Simone,

    veramente quel che dicono nell'articolo alla fine è che è un bug "by design" e quindi non controllabile da Microsoft.. io ti consiglio la stessa soluzione di prima, se puoi modificare la struttura usa direttamente NUMERIC, in alternativa casta tutto in live quando esegui i calcoli.

    Un saluto

    lunedì 15 aprile 2013 07:51