[SQL SERVER 2008] Manipulation de chiffres (arrondis...)

Bonjour je souhaite récupérer des chiffres calculés en utilisant des arrondis :
Voici ma requête de test :

SELECT Article.Quantite * Article.PrixVente AS Montant, Round(Article.Quantite * Article.PrixVente, 2) AS MontantArrondi,

Dans mon exemple, Article.Quantite vaut 25 et Article.PrixVente vaut 0.233
J’obtiens ceci :

Montant MontantArrondi 5.825 5.82

Or, je souhaite obtenir un arrondi par défaut c’est à dire 5.83. Je continue mes tests et ajoute ceci :

SELECT Article.Quantite * Article.PrixVente AS Montant, Round(Article.Quantite * Article.PrixVente, 2) AS MontantArrondi, Round(5.825,2) AS ARRONDI_NOMBRE_BASE, 0.233 * 25 AS CALCUL_NOMBRE, Round(0.233 * 25,2) AS ARRONDI_CALCUL_NOMBRE,

Et là, curieusement j’obtiens ça :

Montant MontantArrondi ARRONDI_NOMBRE_BASE CALCUL_NOMBRE ARRONDI_CALCUL_NOMBRE 5.825 5.82 5.830 5.825 5.830

Les questions que je me pose sont :

1/ Pourquoi je n’obtiens pas les même résultats en mettant des chiffres en dur plutôt qu’avec des champs calculés.
2/ Pourquoi l’arrondi est “bon” avec les chiffres en dur
3 Pour quoi il y a 3 chiffres après la virgule et non 2 sur les champs ARRONDI_NOMBRE_BASE et ARRONDI_CALCUL_NOMBRE

4/ Comment obtenir le résultat de ARRONDI_CALCUL_NOMBRE avec des champs calculés ?
Auriez-vous une petite idée ? Faut-il caster préalablement les champs ?

C’est certainement du à des types implicites.

Tu devrais nous indiquer de quelle manière tu stockes Quantite & PrixVente.

[quote=“Styx31, post:2, topic: 50729”]C’est certainement du à des types implicites.

Tu devrais nous indiquer de quelle manière tu stockes Quantite & PrixVente.[/quote]

Les 2 sont stockées avec le type REAL.

Exemple chez moi :

[code]DECLARE @Quantite INT = 25
DECLARE @PrixVente MONEY = 0.233

SELECT
@Quantite * @PrixVente AS Montant,
ROUND(@Quantite * @PrixVente, 2) AS MontantArrondi,
Round(5.825,2) AS ARRONDI_NOMBRE_BASE,
0.233 * 25 AS CALCUL_NOMBRE,
Round(0.233 * 25,2) AS ARRONDI_CALCUL_NOMBRE[/code]

Résultat obtenu :

[code]Montant MontantArrondi ARRONDI_NOMBRE_BASE CALCUL_NOMBRE ARRONDI_CALCUL_NOMBRE


5,825 5,83 5.830 5.825 5.830[/code]

HAHA :smiley: Laisse tomber, ton erreur est là. Et c’est très grave de stocker des montants précis dans des types flottants (tu viens de découvrir une des raisons). MONEY et DECIMAL servent à ça.

Tu remarqueras que sur la page des Data Types, float et real sont stockés dans les « Approximate Numerics »… Je te laisse deviner les conséquences que cela peut avoir.

Et tu peux aussi contrôler ton code applicatif : si tu utilises des float (single) ou des doubles (real), alors jettes toi par la fenêtre de suite.

Dernier point pour ta culture : SQL Server converti automatiquement les nombre décimaux où apparaît un « . » en numeric.

D’où tes différences constatées…

[quote=« Styx31, post:4, topic: 50729 »]Exemple chez moi :

[code]DECLARE @Quantite INT = 25
DECLARE @PrixVente MONEY = 0.233

SELECT
@Quantite * @PrixVente AS Montant,
ROUND(@Quantite * @PrixVente, 2) AS MontantArrondi,
Round(5.825,2) AS ARRONDI_NOMBRE_BASE,
0.233 * 25 AS CALCUL_NOMBRE,
Round(0.233 * 25,2) AS ARRONDI_CALCUL_NOMBRE[/code]

Résultat obtenu :

[code]Montant MontantArrondi ARRONDI_NOMBRE_BASE CALCUL_NOMBRE ARRONDI_CALCUL_NOMBRE


5,825 5,83 5.830 5.825 5.830[/code]

HAHA :smiley: Laisse tomber, ton erreur est là. Et c’est très grave de stocker des montants précis dans des types flottants (tu viens de découvrir une des raisons). MONEY et DECIMAL servent à ça.

Tu remarqueras que sur la page des Data Types, float et real sont stockés dans les « Approximate Numerics »… Je te laisse deviner les conséquences que cela peut avoir.

Et tu peux aussi contrôler ton code applicatif : si tu utilises des float (single) ou des doubles (real), alors jettes toi par la fenêtre de suite.[/quote]

Effectivement si je change ta variable MONEYen type REALje retombe sur la même erreur…

J’ai modifié ma réponse pour donner un peu plus d’informations.

Merci pour ton aide mais j’ai un petit souçi toutefois. J’ai modifié mon type de données sur la colonne PrixVente mais j’ai toujours le même souçi d’arrondi :smiley: 5.82 au lieur de 5.83

Tu mens ! :smiley: Ou bien tu as laissé ton Quantite en REAL :smiley: (Et je parie une bière sur la seconde solution).

[code]DECLARE @PrixVente MONEY = 0.233

SELECT
ROUND(CAST(25 AS NUMERIC) * @PrixVente, 2) AS Montant,
ROUND(CAST(25 AS REAL) * @PrixVente, 2) AS MontantReal[/code]

donne :

[code]Montant MontantReal


5.8300 5,82[/code]

Et c’est la prévalence des types qui provoque ce comportement. REAL * NUMERIC = REAL.

[quote=« Styx31, post:8, topic: 50729 »]Tu mens ! :smiley: Ou bien tu as laissé ton Quantite en REAL :smiley: (Et je parie une bière sur la seconde solution).

[code]DECLARE @PrixVente MONEY = 0.233

SELECT
ROUND(CAST(25 AS NUMERIC) * @PrixVente, 2) AS Montant,
ROUND(CAST(25 AS REAL) * @PrixVente, 2) AS MontantReal[/code]

donne :

[code]Montant MontantReal


5.8300 5,82[/code]

Et c’est la prévalence des types qui provoque ce comportement. REAL * NUMERIC = REAL.[/quote]

Effectivement j’ai laissé Quantite en REAL. Je ne pensais pas que ça poserai de problème… et bien si ! Merci à toi pour toutes ces informations précieuses !

Encore une petite chose, je dois utiliser des chiffres virgules pour Quantité. J’ai fait un test avec Float. Ca a l’air de fonctionner. Il n’y a pas de contre-indication à utiliser ce type de données ?

SI ! Pourtant je te l’ai mis au dessus : NE JAMAIS UTILISER DE VIRGULES FLOTTANTES POUR LES MONTANTS PRECIS.

Donc DECIMAL, INT, et cie. mais rien d’autre sinon tu vas avoir de sérieux problèmes ensuite.

[quote=“Styx31, post:10, topic: 50729”]SI ! Pourtant je te l’ai mis au dessus : NE JAMAIS UTILISER DE VIRGULES FLOTTANTES POUR LES MONTANTS PRECIS.

Donc DECIMAL, INT, et cie. mais rien d’autre sinon tu vas avoir de sérieux problèmes ensuite.[/quote]
OK, Merci !!!

Je plussoies, meme si ca se fait pas trop ici, les float, niveau precision, c’est clairement pas fait pour. DU TOUT.