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

VBA Access Discussion :

Calcul de la Médiane avec regroupement sur un champ [AC-2003]


Sujet :

VBA Access

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 50
    Points : 24
    Points
    24
    Par défaut Calcul de la Médiane avec regroupement sur un champ
    Bonsoir à tous,

    Je cherche à déterminer la médiane sur une de mes tables avec pour subtilité de calculer cette médiane sur un champ de regroupement. Avec l'exemple ci-dessous, je souhaite pour chaque valeur du champ GP déterminer sa médiane.

    GP SF CIR Med
    A 2 AZ 4,5
    A 5 AI 4,5
    A 3 AJ 4,5
    A 1 AA 4,5
    B 4 BB 5
    C 10 CA 11,5
    B 9 BX 5
    B 5 BN 5
    C 13 CF 11,5
    C 12 CX 11,5
    C 11 CR 11,5

    Bien évidemment, j'ai écumé le forum et j'ai trouvé des solutions pour déterminer la médiane sur l'ensemble de ma table sans regroupement mais bon je n'ai pas envie de créer X tables et y appliquer la fonction.

    J'ai également trouvé ceci. Il s'agit d'un code qui selon l'historique de la discussion devrait fonctionner pour déterminer cette médiane avec un regroupement malheureusement chez moi rien y fait.

    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
     Public Function fMediane(strTable As String, strField As String, Optional Arg_Champ_Regroupement As String, Optional Arg_Valeur_Regroupement) As Variant
     
    Dim oDBS As DAO.Database
    Dim oRST As DAO.Recordset
    Dim blnEven As Boolean
    Dim vntMedian As Variant
     
      Set oDBS = CurrentDb()
        If IsMissing(Arg_Regroupement) Then
        SQL = "SELECT " & strTable & ".* FROM " & strTable & " ORDER BY " & strTable & "." & strField & ";"
      Else
        SQL = "SELECT " & strTable & ".* FROM " & strTable & " WHERE " & strTable & ".[" & Arg_Champ_Regroupement & "]=" & Arg_Valeur_Regroupement & " ORDER BY " & strTable & "." & strField & ";"
     
      End If
     
      Set oRST = oDBS.OpenRecordset(SQL, dbOpenDynaset)
     
     
      If oRST.EOF = False Then
         oRST.MoveLast
         'Y a-t'il un nombre pair d'enreistrements ?
         blnEven = (oRST.RecordCount Mod 2 = 0)
         'Classer en décroissant si on a un nombre pair
         oRST.PercentPosition = 50
         vntMedian = oRST.Fields(strField)
         If blnEven Then
             oRST.MoveNext
             'faire la moyenne entre cet enregistrement et le précédent
             vntMedian = (vntMedian + oRST.Fields(strField)) / 2
         End If
      End If
     
      fMediane = vntMedian
      oRST.Close
      Set oRST = Nothing
      Set oDBS = Nothing
     
    End Function

    Je ne comprends pas à quoi correspond ce "Arg_Valeur_Regroupement" s'agit-il de mon champ GP des valeurs du champ GP?

    Pouvez-vous me venir en aide ?

    Merci d'avance,

  2. #2
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    12 619
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12 619
    Points : 56 854
    Points
    56 854
    Billets dans le blog
    40
    Par défaut
    bonjour,

    Citation Envoyé par Antisthene Voir le message
    Je cherche à déterminer la médiane sur une de mes tables avec pour subtilité de calculer cette médiane sur un champ de regroupement.
    a priori, tu écris une requête avec regroupement (en s'aidant des assistants requête) :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT GP, fMediane("laTable", "Med", "GP", GP) as ValeurMediane
    FROM laTable
    GROUP BY GP

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fMediane("laTable", "Med", "GP", GP)
    1er argument : nom de la table entre guillemets
    2è argument : nom du champ sur lequel tu calcules la médiane
    3è argument : nom du champ à filtrer
    4è argument: valeur courante du champ à filtrer

    à adapter sans doute...

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 50
    Points : 24
    Points
    24
    Par défaut
    Bonsoir fLeb,

    Merci pour ces explications.
    Malheureusement à mon grand désarrois la fonction fMediane à besoin qu'on renseigne le groupe sur lequel la médiane doit être calculée.
    J'aurais aimé trouver une fonction qui pour chaque groupe de ma table de départ la calcul de telle manière à avoir en sorti une table comme celle-ci :

    GP SF CIR Med
    A 2 AZ 4,5
    A 5 AI 4,5
    A 3 AJ 4,5
    A 1 AA 4,5
    B 4 BB 5
    C 10 CA 11,5
    B 9 BX 5
    B 5 BN 5
    C 13 CF 11,5
    C 12 CX 11,5
    C 11 CR 11,5

    Pour cela, il faudrait une boucle qui sélectionne toutes les valeurs distinctes du champ GP de telle manière à les rentrer dans le SQL à la place du champ "Arg_valeur_regroupement"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SQL = "SELECT " & strTable & ".* FROM " & strTable & " WHERE " & strTable & ".[" & Arg_Champ_Regroupement & "]=" & Arg_Valeur_Regroupement & " ORDER BY " & strTable & "." & strField & ";"
    Je ne sais pas si cela existe à existe en tous cas ça me semble bien trop compliquer. Une idée peut-être?

  4. #4
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    12 619
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12 619
    Points : 56 854
    Points
    56 854
    Billets dans le blog
    40
    Par défaut
    oups, la médiane est calculée sur le champ SF, c'est donc :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT GP, fMediane("LaTableDeDepart", "SF", "GP", GP) AS ValeurMediane
    FROM LaTableDeDepart
    GROUP BY GP

    Tu appelles cette requête ReqMediane que tu réutilises pour obtenir ton tableau avec la requête:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT GP, SF, CIR, ValeurMediane
    FROM LaTableDeDepart INNER JOIN ReqMediane
    ON LaTableDeDepart.GP=ReqMediane.GP

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 50
    Points : 24
    Points
    24
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT GP, fMediane("LaTableDeDepart", "SF", "GP", GP) AS ValeurMediane
    FROM LaTableDeDepart
    GROUP BY GP
    Ce que je ne comprends pas c'est que dans le code ci-dessus le dernier paramètre GP correspond à une des valeurs du champ GP. C'est à dire qu'il faut que je lui dise si c'est A ou B ou C manuellement sachant que j'ai en réalité plus de 80 valeurs différentes pour GP je ne vais pas m'amuser à faire 80 fois cette fonction. J'aimerais qu'il calcul de lui-même cette médiane pour tous les GP sans que je lui dise lequel.

    J'imagine que ça complique bien des choses.

  6. #6
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    12 619
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12 619
    Points : 56 854
    Points
    56 854
    Billets dans le blog
    40
    Par défaut
    Citation Envoyé par Antisthene Voir le message
    C'est à dire qu'il faut que je lui dise si c'est A ou B ou C manuellement sachant que j'ai en réalité plus de 80 valeurs différentes pour GP je ne vais pas m'amuser à faire 80 fois cette fonction.
    il te demande la valeur à chaque fois ? Ce n'est pas normal, il ne devrait pas. Tu pourrais décrire ce qui se passe plus précisément (message d'erreur ?)

    Est-ce que le champ GP est bien de type Texte ?

  7. #7
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    12 619
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12 619
    Points : 56 854
    Points
    56 854
    Billets dans le blog
    40
    Par défaut
    Si GP est de type Texte, il faut rajouter les guillemets simples (en rouge ci-dessous):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SQL = "SELECT " & strTable & ".* FROM " & strTable & " WHERE " & strTable & ".[" & Arg_Champ_Regroupement & "]= '" & Arg_Valeur_Regroupement & "' ORDER BY " & strTable & "." & strField & ";"

  8. #8
    Expert confirmé
    Avatar de vodiem
    Homme Profil pro
    Vivre
    Inscrit en
    Avril 2006
    Messages
    2 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Vivre
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2006
    Messages : 2 895
    Points : 4 325
    Points
    4 325
    Par défaut
    Salut f-leb et Antisthene,

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT GP, fMediane("LaTableDeDepart", "SF", "GP", GP) AS ValeurMediane FROM LaTableDeDepart
    (pas de regroupement!)

    avec la fonction fMediane modifiée:
    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
    Public Function fMediane(strTable As String, strField As String, Optional Arg_Champ_Regroupement As String, Optional Arg_Valeur_Regroupement) As Variant
     
    Dim oDBS As DAO.Database
    Dim oRST As DAO.Recordset
    Dim blnEven As Boolean
    Dim vntMedian As Variant
     
      Set oDBS = CurrentDb()
        If IsMissing(Arg_Regroupement) Then
        SQL = "SELECT " & strTable & ".* FROM " & strTable & " ORDER BY " & strTable & "." & strField & ";"
      Else
        SQL = "SELECT " & strTable & ".* FROM " & strTable & " WHERE " & strTable & ".[" & Arg_Champ_Regroupement & "]='" & Arg_Valeur_Regroupement & "' ORDER BY " & strTable & "." & strField & ";"
     
      End If
     
      Set oRST = oDBS.OpenRecordset(SQL, dbOpenDynaset)
     
     
      If oRST.EOF = False Then
         oRST.MoveLast
         'Y a-t'il un nombre pair d'enreistrements ?
         blnEven = (oRST.RecordCount Mod 2 = 0)
         'Classer en décroissant si on a un nombre pair
         oRST.AbsolutePosition = (oRST.RecordCount \ 2) + blnEven
         vntMedian = oRST.Fields(strField)
         If blnEven Then
             oRST.MoveNext
             'faire la moyenne entre cet enregistrement et le précédent
             vntMedian = (vntMedian + oRST.Fields(strField)) / 2
         End If
      End If
     
      fMediane = vntMedian
      oRST.Close
      Set oRST = Nothing
      Set oDBS = Nothing
     
    End Function
    > modifications :
    . type Arg_Valeur_Regroupement string => ajout de cotes.
    . pour obtenir un résultat cohérent (chez moi), modification de ma méthode de positionnement : non plus .PercentPosition mais .AbsolutePosition.
    > remarque sur cette fonction: à défaut de valeur Arg_Valeur_Regroupement il serait judicieux de prendre le contenu dans Arg_Champ_Regroupement, vu qu'en plus, étant optionnel dans ce cas cela produirait une erreur.


  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 50
    Points : 24
    Points
    24
    Par défaut
    Bonsoir à tous,

    J'ai pu tester rapidement ceci au travail aujourd'hui et à mon grand bonheur ( ce coup-ci) cela semble plutôt bien fonctionner, je n'ai pas de gestionnaire de demande qui s'alarme
    Effectivement mon champ GP était de type texte.

    J'ai également appliquer les modifications du absolutePosition à la place du percentPosition. Je n'ai pas regardé l'impact.

    Sinon j'aurais besoin de quelques explications quant au code pouvez-vous me détailler un peu? J'ai mis mes interrogations dedans;


    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
      If oRST.EOF = False Then
         oRST.MoveLast
         'Y a-t'il un nombre pair d'enreistrements ?
         ' A quoi est égal la variable blnEven si le reste de la division est égal à 0 et si le reste est différent de 0? Est-ce égal à "vrai" (ie 1) ou "faux" (ie 0)
    
         blnEven = (oRST.RecordCount Mod 2 = 0)
    
         'Classer en décroissant si on a un nombre pair
         'Je ne vois pas ou ce fait le test du nombre pair dans la ligne dessous? Est-ce ce "+ blnEven"? Et ou vois t-on qu'elle est triée par ordre décroissant ?
         A quoi est égal ce oRST.AbsolutePosition si c'est pair et si c'est impair je ne voie pas pourquoi on ajoute blnEven?
    
         oRST.AbsolutePosition = (oRST.RecordCount \ 2) + blnEven
         vntMedian = oRST.Fields(strField)
         If blnEven Then
             oRST.MoveNext
             'faire la moyenne entre cet enregistrement et le précédent
             vntMedian = (vntMedian + oRST.Fields(strField)) / 2
         End If

    Merci d'avance pour votre aide

  10. #10
    Expert confirmé
    Avatar de vodiem
    Homme Profil pro
    Vivre
    Inscrit en
    Avril 2006
    Messages
    2 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Vivre
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2006
    Messages : 2 895
    Points : 4 325
    Points
    4 325
    Par défaut
    Citation Envoyé par Antisthene
    A quoi est égal la variable blnEven si le reste de la division est égal à 0 et si le reste est différent de 0? Est-ce égal à "vrai" (ie 1) ou "faux" (ie 0)
    (oRST.RecordCount Mod 2) vaut 0 si c'est pair autrement il vaut 1 (reste de la division par 2).
    (oRST.RecordCount Mod 2 = 0) vaut si c'est pair : true autrement false, soit respectivement -1 et 0 puisque c'est ainsi qu'Access le stock.

    Citation Envoyé par Antisthene
    >Je ne vois pas ou ce fait le test du nombre pair dans la ligne dessous? Est-ce ce "+ blnEven"?
    >Et ou vois t-on qu'elle est triée par ordre décroissant ?
    >A quoi est égal ce oRST.AbsolutePosition si c'est pair et si c'est impair je ne voie pas pourquoi on ajoute blnEven?
    > le gars il a pas dit où en dessous, mais il est bien en dessous: ^^
    "If blnEven Then"...
    > ben il a eu l'idée avec un ORDER BY sur strField mais il a oublié d'ajouter DESC ^^
    'Classer en décroissant si on a un nombre pair
    il a aussi oublié d'ajouter " et si on n'a pas non plus de nombre pair..." ^^
    et puis que si c'est croissant ou décroissant ça ne changeait rien au résultat
    > oRST.AbsolutePosition se trouve à la moitié des enregistrements avec (oRST.RecordCount \ 2) et avec blnEven : moitié-1 si c'est pair, moitié+0 si c'est impair.
    il aurait été plus clair de faire un test de parité et ajouter en conséquence... mais le mec qui t'a pondu ca il est "économe" ^^
    sinon il est possible de faire aussi avec oRST.PercentPosition = 50 et repositionner en conséquence (du fait qu'AbsolutePosition début à 0).

    Citation Envoyé par Antisthene
    Je n'ai pas regardé l'impact
    moi si: les résultats ne sont pas les mêmes.
    mais tu me diras, c'est sur que c'est pas avec ce type de détail que tu gagneras au loto... encore que... en se trompant de médian on peux éventuellement s'éviter une aberration... enfin faut pas trop compter dessus quand même...


  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 50
    Points : 24
    Points
    24
    Par défaut
    Merci Vodiem pour ce decryptage aux petits oignons, j'y vois nettement plus clair en même temps je partais de très loin.

    J'en profite pour remercier tous ceux qui ont contribué à cette discussion et qui m'ont aidé.

    Je clos donc cette discussion.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 13/03/2017, 18h45
  2. [AC-2013] Problème Requête avec Regroupement sur Champ Somme
    Par kesme dans le forum Access
    Réponses: 4
    Dernier message: 23/03/2015, 11h37
  3. Concaténation avec regroupement sur un champs
    Par isabelle b dans le forum VBA Access
    Réponses: 12
    Dernier message: 23/05/2008, 07h27
  4. Requete avec filtre sur un champ
    Par podz dans le forum Langage SQL
    Réponses: 7
    Dernier message: 09/02/2005, 14h37
  5. Recherche d'un mot avec LIKE sur plusieurs champs
    Par reynhart dans le forum Langage SQL
    Réponses: 16
    Dernier message: 26/11/2004, 17h41

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