Calcul de rang – Variante 3

Dans deux articles précédents, intitulés Calcul de rang et Calcul de rang avec critère, il était question de déterminer le rang d’un élève à partir de sa moyenne. La technique pouvant bien sûr s’adapter à tous types de classements.

Dans le deuxième article, on a vu comment déterminer le rang par classe, et non plus sur toute la table des élèves. Dans l’exemple, il s’agissait de créer une requête paramétrée, de taper le nom de la classe, et d’obtenir les rangs d’élèves de cette classe, et uniquement de cette classe.

On m’a demandé comment faire en sorte d’obtenir les rangs de toutes les classes, en une seule fois (la requête n’étant plus paramétrée). Bonne nouvelle : c’est assez simple à aménager, si vous avez suivi les articles précédents ! Sauf pour la version SQL bien sûr… 😉

Calcul de rang - Liste de toutes les classes

Méthode 1 : calcul de rang par DCount

Dans l’article précédent, on en était resté à cette formule :

… où [Entrer la classe] était un paramètre à renseigner manuellement à l’exécution de la requête.

Pour supprimer ce critère paramétré, faites les 3 aménagements suivants dans votre requête :

  1. Sur la grille de requête, supprimez le paramètre, sous le champ Classe. On souhaite effectivement calculer les rangs pour toutes les classes, cette fois.
  2. Ajoutez peut-être un tri croissant sur la classe, histoire d’y voir plus clair dans la liste finale !
  3. Remplacez la formule ci-dessus par celle-ci, où on a remplacé le paramètre par le champ Classe de chaque élève :

C’est tout ! Exécutez la requête pour vérifier.

Calcul de rang - Liste de toutes les classes

Méthode 2 : calcul de rang par sous-requête

En version SQL, c’est un peu plus lourd. Voilà qui peut faire l’affaire pour la formule de calcul de rang :

Vous aimerez aussi...

21 réponses

  1. bmazoyer dit :

    Bonjour,

    J’ai posté un commentaire le 15 août mais il semble avoir disparu depuis. A-t-il été effacé et pour quelle raison ?
    Je repose ma question à tout hasard: j’ai testé la méthode « calcul de rang par sous-requête » en copiant simplement votre code dans le « générateur ». D’une part, Access me demande de définir le critère T1.[Moyenne]. D’autre part, si je modifie le code pour définir T1 de cette manière :
    (Rang: (SELECT COUNT(*) + 1 FROM (SELECT DISTINCT [Classe],[Moyenne] FROM [tblElèves] AS T2 WHERE [Classe] = [Classe])T1 WHERE (T2.[Moyenne] > T1.[Moyenne]) AND (T1.Classe = T2.Classe))
    j’obtiens bien un résultat, mais dans la colonne « Rang » je n’obtiens que des 1.
    Savez-vous d’où provient l’erreur ?
    Merci d’avance pour votre réponse.

    • Hervé Inisan dit :

      Je n’ai pas vu passer l’autre commentaire (sauf doute l’anti-spam du site).
      Pour revenir à la question : est-ce que la variante avec DCount() fonctionne ?
      (ce sera plus simple pour la mise au point, dans un 1er temps)

      • bmazoyer dit :

        Oui, la méthode avec DCount fonctionne. Mais j’essaye de réduire le temps de traitement de ma base de données (actuellement près d’1/4 d’heure) et il paraît que les fonctions de domaines sont très lentes.

        • Hervé Inisan dit :

          Les fonctions de domaines sont effectivement un peu lentes. Maintenant, 1/4 d’heure pour une requête, ça me semble trèèès long. Il y a peut-être d’autres choses à optimiser en amont. La table contient un grand nombre de lignes ?

          • bmazoyer dit :

            Il n’y a pas qu’une seule requête: deux requêtes avec un Dcount traitent deux tables d’environ 250000 lignes chacune. Ensuite j’ai deux requêtes avec un DSum et une requête avec un DMin. Et l’ensemble dure à peu près 1/4 d’heure.

          • bmazoyer dit :

            Il n’y a pas qu’une requête : deux requêtes avec un Dcount puis deux requêtes avec un DSum s’exécutent sur deux tables, et enfin une requête avec un DMin. Ce matin, l’ensemble durait 1/4 d’heure. Maintenant j’ai trouvé un moyen de filtrer mes tables importées pour passer d’environ 250 000 lignes à 50 000 lignes, et l’ensemble dure à peu près 4 minutes. Ce qui reste très long.

          • Hervé Inisan dit :

            Et c’est bien un DCount() qu’il faut ? Une requête de regroupement ou d’analyse croisée ne pourrait pas faire l’affaire ?
            En d’autres termes :
            – Quelles sont les données sources ?
            – Quel est l’objectif de traitement derrière ?

        • bmazoyer dit :

          Les données sources:

          -une table “échéances” qui indique les différentes dates et quantités de livraison convenues avec les fournisseurs pour chaque produit donné (identifié par le couple “document achat” et “poste”)
          Ce qui donne :
          document achat ; poste ; date livraison ; quantité éché
          A ;10 ; 12.08.2014 ; 2
          A ;10 ; 19.08.2014 ; 8
          A ;10 ; 19.08.2014 ; 10
          B ;10 ; 14.08.2014 ; 100

          – une table “historique commande” qui indique pour chaque produit à quelle date (date pièce) il a été livré et en quelle quantité:
          document achat ; poste ; date pièce ; quantité
          A ; 10 ; 13.08.2014; 10
          B ; 10 ; 20.08.2014; 50
          B ; 10 ; 22.08.2014; 50

          L’objectif : obtenir pour chaque ligne de la table échéance la date où une quantité supérieure ou égale à la somme des “quantités éché” antérieures a été livrée.
          Ce qui donne, dans notre exemple:
          document achat ; poste ; date livraison ; quantité éché ; date pièce
          A ;10 ; 12.08.2014 ; 2 ; 13.08.2014
          A ;10 ; 19.08.2014 ; 8 ; 13.08.2014
          A ;10 ; 19.08.2014 ; 10 ; Null
          B ;10 ; 14.08.2014 ; 100 ; 22.08.2014

          Comment je procède : pour chaque table, je calcule le “rang” de chaque date de livraison d’un produit donné à l’aide d’un DCount. Ensuite pour chaque ligne de chaque table, je fais la somme des quantités des lignes de rang inférieur (toujours pour chaque produit donné) à l’aide d’un DSum. Enfin, pour chaque ligne de la table échéance, je recherche dans la table “historique commande” la première date où a somme requise a été atteinte, à l’aide d’un DMin.

          • Hervé Inisan dit :

            J’ai regardé rapidement (tout ça demande des tests 😉 ).
            Est-ce que la différenciation des dates dans la table Commandes est importante ? Je ne connais pas le projet, mais je me dis :
            1. Que si on cumule « complètement » sur une date donnée (le 19/08 donnerait 20), on a un total journalier plus pratique à gérer, et plus synthétique (est-ce qu’on doit considérer qu’on a une livraison partielle sur une journée ?).
            2. Que dans ce cas on éviterait le calcul de rang.
            3. Que sinon, si on doit distinguer les opérations journées, il manque un champ dans les exemples pour les différencier (une clef primaire).

  2. lecoq dit :

    J’ai essayé votre formule de rang variante 3, mais j’ai un problème avec la requête et j’ai le message suivant dès que j’exécute la requête « Type de données incompatible dans l’expression du critère » et Access est bloqué. J’ai testé votre exemple et sans problème. En fait je teste sur un champs numérique et votre modèle est alpha/numérique; je me demande si le problème ne vient pas de là. Faut-il modifier la formule en fonction du mode du champs. Je suis inscrit sur votre site sous l’id Lray ..
    Merci d’avance pour votre réponse.
    Bàv

    • Hervé Inisan dit :

      Ça vient certainement de là, effectivement : les chaînes sont délimitées (en SQL) par l’apostrophe, alors que les nombres n’ont pas de délimiteur.
      Dans mon exemple, si la classe était un nombre, on adapterait la formule de cette manière :

      • lecoq dit :

        Merci pour votre réponse. Dans cette formule, je reçois un rang identique vu que j’ai une moyenne et une classe identique mais j’ai un autre champs qui pourrait les partager. Comment modifier cette formule pour pouvoir modifier les rangs identiques.

        J’ai également une autre question, lorsque j’ai le rang, je devrais choisir l’avant dernier champs (exemple si j’ai 2 rangs je dois prendre le 1ier, 3 rang =2 et ainsi de suite) afin d’ éditer un champs qui est sur la même ligne. Quel formule dois je faire.
        Merci de me dire comment je dois poster ce genre de question dans votre forum.
        Je vous remercie d’avance pour vos réponses . Bàv.

  3. Hervé Inisan dit :

    donald > Si les données sont dans des tables liées, l’idée est de construire d’abord une requête pour relier ces tables, et d’appliquer les techniques de cette série d’articles à la requête, plutôt qu’à une table.

    PS : Merci de ne pas poster en majuscules : dans un message, c’est assimilé au fait de crier. 😉

  4. donald dit :

    JE N’ARRIVE PAS A CALCULER LE RANG DANS ACCESS 2007 AVEC DES CHAMP APPARTENANT A DES TABLES DIFFÉRENTES: CLASSE, ELEVES, MATIERE, …

  5. Hervé Inisan dit :

    Jacques Gronier > Merci pour le retour ! 🙂

  6. Jacques Gronier dit :

    Merci pour le calcul du rang sur l’ensemble d’une population, par « classe », c’est nettement plus élégant et plus rapide qu’avec « nb.si.ens » sous Excel

  7. Hervé Inisan dit :

    hassan > C’est un site Web, donc tu as déjà tous les articles disponibles comme tu le souhaites. 😉

    Tu peux naviguer par les catégories (à gauche), les tags, la zone de recherche, entre autres.

  8. hassan dit :

    merci pour votre cours
    et je vous seari très reconnaidssant si je peux avoir une copie des articles précédents
    merci encore

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *