IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes et SQL. Discussion :

Résultat de requête troublant : ,0000001


Sujet :

Requêtes et SQL.

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 206
    Points : 127
    Points
    127
    Par défaut Résultat de requête troublant : ,0000001
    Bonsoir à tous,
    En continuant de perfectionner mon moteur de recherche, j'utilise des requêtes de regroupement afin de calculer des sommes par postes.
    Celles-ci, et d'une manière qui me semble aléatoire, même si elle ne l'est probablement pas, me retourne quelques valeurs étranges, avec bon nombres de 0 (suivi d'un autre chiffre) ou de 9 après la virgule.
    J'ai donc essayé quelques requête sultra simple à l'aide de l'assistant du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT Tblfluxcash.nomcompte, Sum(Tblfluxcash.montant) AS SommeDemontant
    FROM Tblfluxcash
    GROUP BY Tblfluxcash.nomcompte;
    Et idem : certains regroupement indiquent un résultat fort étrange.
    Le champs "montant" est un champs numérique réel double, avec un nombre de décimale "auto" ; l'ensemble des valeurs qui y sont enregistrées ont au plus deux chiffres après la virgule. (par vérification visuelle dans la table, ce qui correspond au enregistrements effectués via le formulaire !)
    S'il n'y avait que ce milliardième de centime de différence, pas de soucis, malheureusement il semble qu'il y ait un "cumul" en appliquant des requêtes sur d'autres, pouvant mener à une différence plus importante !
    J'ai par exemple un poste avec une différence totale supérieure à 1 lors du regroupement, alors qu'un DSUM sur la table source indique le bon résultat.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Me.lbltotal.Caption = Round(DSum("[montanteur]", "Rqttotal"), 2)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            Me.lsttotal.RowSource = "SELECT Rqttotal.posteflux1 as [Poste principal], Sum(Rqttotal.montanteur) as Somme, 'NA' as [%] " & _
                                    "FROM Rqttotal " & _
                                    "GROUP BY Rqttotal.posteflux1 " & _
                                    "ORDER BY Rqttotal.posteflux1"
            Me.lsttotal.Requery
    Quelqu'un aurait une idée d'où peut provenir ce soucis ? Vers où chercher - que regarder ?
    En vous remerciant d'avance,

  2. #2
    Expert éminent sénior
    Avatar de tee_grandbois
    Homme Profil pro
    retraité
    Inscrit en
    Novembre 2004
    Messages
    8 648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Novembre 2004
    Messages : 8 648
    Points : 14 626
    Points
    14 626
    Par défaut
    Bonsoir,
    Change tes données en type Monétaire, c'est le type de données utilisé pour les montants (en général on utilise le réel double pour des calcul mathématiques et pour stocker des très très grandes valeurs).
    En attendant, tu peux convertir ton champ en type Monétaire dans la requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT Tblfluxcash.nomcompte, Sum(Ccur(Tblfluxcash.montant)) AS SommeDemontant
    Quand on est derrière l'écran on n'a aucun clavier sous les mains ...
    ah non ? donc devant l'écran c'est la connectique ?

  3. #3
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 193
    Points : 28 077
    Points
    28 077
    Par défaut
    Citation Envoyé par wulfram Voir le message
    un champs numérique réel double,
    très certainement de là.

    les nombres réels double, comprendre nombre à virgule flottante double précision, ne sont pas de nombres exacts (voir norme IEEE754).
    De part la codification du nombre, toutes les valeurs ne peuvent pas être représentées, certaines sont incodifiables. Le nombre stocke donc, non pas la valeur exacte, mais un arrondi, la valeur codifiable la plus proche. Ce qui fait que pour certaines valeurs, tu ne vas stocker X, mais X - 0.00000000000000001 par exemple.
    La propagation de ces arrondis dans les calculs peuvent, à force, donner lieu aux erreurs que tu mentionne.

    C'est la raison pour laquelle, lorsque cette erreur est préjudiciable, on évite de stocker des valeurs monétaires dans des types à virgule flottantes (et c'est pourtant ce que tout le monde fait).
    Suivant les SGBD, on utilisera le type Currency, s'il existe (et est prévu pour ça), sinon des types décimaux, ou numeric, ... voir la doc du sgbd pour savoir lequel est le plus approprié

    Et attention, avec les nombres à virgule flottante, la valeur saisie n'est pas forcément celle réellement enregistrée, la valeur affichée n'est pas forcément, non plus celle réellement lue.
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  4. #4
    Modérateur

    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    15 331
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2005
    Messages : 15 331
    Points : 23 786
    Points
    23 786
    Par défaut
    En complément des réponses précédentes.

    Le type currency a la réputation d'être bugée en Access et il recommandé de ne pas l'utiliser.
    Personnellement je n'ai jamais vérifié mais je ne l'utilise pas.

    On peut minimiser les problèmes en faisant des arrondis et là aussi la fonction round()a la réputation d'être bugée. Personnellement j'utilise format() qui semble fonctionner sans surprise.
    Quelque chose comme Val(replace(Format(UnNombre, "0.0000"), ",", ".")) car val ne marche qu'avec le "." comme séparateur de décimales. Je fais cela, soit dans chaque calcul, soit sur le résultat final.

    A+
    Vous voulez une réponse rapide et efficace à vos questions téchniques ?
    Ne les posez pas en message privé mais dans le forum, vous bénéficiez ainsi de la compétence et de la disponibilité de tous les contributeurs.
    Et aussi regardez dans la FAQ Access et les Tutoriaux Access. C'est plein de bonnes choses.

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 206
    Points : 127
    Points
    127
    Par défaut
    Bonsoir à tous,
    En changeant directement le type de numérique de l'ensemble des champs concernés à un type décimal avec 3 chiffres après la virgule, il semble qu'en effet le problème soit résolu.
    Le reste du code semble toujours fonctionner correctement, sans y apporter aucunes modifications, mais je vais devoir vérifier cela plus en profondeur !
    Le changement a tout de même eu pour effet une perte nette sur l'un des comptes, de quelques centimes, dont je n'arrive pas à trouver l'origine : les mouvements correspondent bien à ceux avant modification ; le solde est par contre différent de celui calculé par la banque.

    Je me demandais par ailleurs de l'intérêt d'utiliser le "format()" ; avant un "INSERT" j'utilise actuellement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    virgule = Replace(i, ",", ".")
    , la propriété du champs semble s'occuper elle même de la mise au format adéquat. Cela ne me coûte rien de rajouter une fonction supplémentaire, mais est-ce bien utile ?
    En attendant, je passe le problème en résolu, bien que du travail m'attendre avant d'être plus que certain que ce soit vraiment le cas !

    Une bonne soirée à tous,

  6. #6
    Expert éminent sénior
    Avatar de tee_grandbois
    Homme Profil pro
    retraité
    Inscrit en
    Novembre 2004
    Messages
    8 648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Novembre 2004
    Messages : 8 648
    Points : 14 626
    Points
    14 626
    Par défaut
    la propriété du champs semble s'occuper elle même de la mise au format adéquat. Cela ne me coûte rien de rajouter une fonction supplémentaire, mais est-ce bien utile ?
    Ce n'est pas utile si tu as choisi le type décimal mais je me demande pourquoi tu autorises 3 décimales, avec quelle monnaie travailles-tu ?
    Quand on est derrière l'écran on n'a aucun clavier sous les mains ...
    ah non ? donc devant l'écran c'est la connectique ?

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 206
    Points : 127
    Points
    127
    Par défaut
    Avec des monnaies différentes ; j'utilise donc un taux de change pour certaines opérations, donc 4 décimales (je suis passé à quatre depuis !) me semble mieux convenir, sans avoir de "coût" important en terme de performances. (surtout que ma base est une véritable usine à gaz, que je pourrais sans aucun doute améliorer en re-codant de grandes parties quand je penserai que l'outil est suffisamment complet !)
    La prochaine étape serait d'arriver à récupérer le taux de change directement d'un site internet pour calculer mes différents soldes en temps "réel", mais c'est plus une envie d'apprendre qu'un besoin, donc je garde la question pour moi le temps de me pencher dessus !
    Pour ce qui est de l'affichage, par contre, je me contente d'un arrondi à la seconde décimale.

  8. #8
    Expert confirmé Avatar de nico84
    Homme Profil pro
    Consultant/développeur ERP
    Inscrit en
    Mai 2008
    Messages
    3 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Consultant/développeur ERP
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 3 089
    Points : 5 206
    Points
    5 206
    Par défaut
    Bonjour,

    Voici pour info une fonction qui lit les taux de change du jour sur le net :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    '16.5d LECTURE DE DEVISES AU FORMAT JSON 
    Public Sub MajDevises(Optional bilan As Boolean = False)
    Dim http As MSXML2.ServerXMLHTTP, Liste As String, rado As New adodb.Recordset, nb As Integer, i As Integer, s As String
    100 nb = 0 'nombre de devises mises à jour
    102 Liste = ""
     
        'Lecture du flux
        If Not Mode_debug Then On Error GoTo suite:
    105 Set http = New MSXML2.ServerXMLHTTP
    106 http.Open "GET", "http://api.fixer.io/latest", False
    107 http.send ""
        'En cas de réussite, le code renvoyé est 200
    110 If http.Status <> 200 Then
    111   nb = http.Status
    112   Liste = ""
        Else
    115   Liste = http.responseText
        End If
    116 Set http = Nothing
    'MsgBox liste
    '{"base":"EUR","date":"2016-06-22","rates":{"AUD":1.5033,"BGN":1.9558,"BRL":3.8357,"CAD":1.4399,"CHF":1.083,"CNY":7.4227,"CZK":27.071,"DKK":7.4384,"GBP":0.76793,"HKD":8.7524,"HRK":7.52,"HUF":314.42,"IDR":14988.34,"ILS":4.3471,"INR":76.1553,"JPY":118.01,"KRW":1297.62,"MXN":21.0048,"MYR":4.543,"NOK":9.3555,"NZD":1.5732,"PHP":52.434,"PLN":4.3785,"RON":4.526,"RUB":72.266,"SEK":9.3468,"SGD":1.5112,"THB":39.716,"TRY":3.275,"USD":1.1283,"ZAR":16.577}}
    suite:
    If Not Mode_debug Then On Error GoTo err:
    120 If Liste > "" Then
    122   rado.Open "SELECT * FROM devises WHERE code3<>'EUR' order by code3;", cnx, adOpenStatic
    124   While Not rado.EOF
    126     i = InStr(Liste, """" & rado!code3 & """:")
    128     If i > 0 Then
    130       s = Mid(Liste, i + 6, 12)
    132       If InStr(s, ",") > 1 Then s = Left(s, InStr(s, ",") - 1)
    133       s = Replace(s, ".", ",")
    134       If IsNumeric(s) And s > "0" Then
    136         cnx.Execute "UPDATE devises SET taux=" & Num(1 / s, 6) & ", Dmodif=" & IIf(msql, "get", "") & "date() WHERE code3='" & rado!code3 & "'"
    138         nb = nb + 1
            End If: End If
    140     rado.MoveNext
          Wend
        End If
    142 If bilan Then MsgBox nb & " devises actualisées."
        Set rado = Nothing
        Exit Sub
    err: Call message("Erreur " & err.Number & "/" & Erl & " dans api_stock.MajDevises(statut " & nb & ") : " & err.description)
    End Sub
    Utilisez Planet, gestion d'entreprise gratuite pour TPE / PME

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    206
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 206
    Points : 127
    Points
    127
    Par défaut
    Merci bien nico84, c'est très aimable à vous, à part que maintenant je vais vraiment devoir me plonger sur le sujet pour adapter le code à ma structure, et surtout... le comprendre !
    La page internet utilisée a une structure tout à fait adaptée, ce qui ne m'aidera pas à récupérer les informations par moi-même si jamais elles devaient se présenter sous un autre format ! (il faudra à terme que je récupère d'autres informations que les taux de change)
    En attendant je vous remercie, ne vous sentez pas obligé de me mettre sur une autre piste, ce n'est, malheureusement, pas ma priorité actuelle !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL] Affichage de 2 lignes d'un résultat de requête
    Par JohanProg dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 04/10/2005, 15h42
  2. Réponses: 7
    Dernier message: 26/09/2005, 17h50
  3. table comme résultat de requête
    Par nafnaf625 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 10/05/2005, 11h51
  4. Comparaison de résultats de requêtes
    Par Nyx de Tours dans le forum Requêtes
    Réponses: 7
    Dernier message: 31/07/2004, 15h49
  5. Trier aléatoirement un résultat de requête
    Par ang36 dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 08/01/2004, 17h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo