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

 Delphi Discussion :

Problème requête selection


Sujet :

Delphi

  1. #41
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    pour l'impression ou l'affichage :
    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
     
    function gluIDs(aIDs: array of integer): string;
    var L,F,T : integer;
    begin
      result := '';
     
      L := Length(aIDs);
      F := 0;
      T := 0;
      while T < L do
      begin
        F := T;
     
        while (aIDs[T+1] = aIDs[T]+1) and (T < L) do
          inc(T);
     
        if (T < L+1) and (F < T) then
        begin
          result := result + format('%d-%d',[aIds[F], aIDs[T]])
        end
        else
          result := result + intToStr(aIds[T]);
     
        inc(T);
        if T < L then
          result := result + ',';
      end;
    end;
    Mais voila, tu dois juste fournir un tableau d'integer disctinct correspondant aux id.
    Et pourquoi je dis qu'il faut un champs Id_localite disctinct dans le client pour eviter de faire une fonction lourde "ungluIds->array of integer".
    Après rien n'empèche, mais j'ai peur qu'avec 100000 entrées ou plus, on mette plus de 10 secondes à générer et corriger les ids.

    gluIds mets 5 seconde (4437ms) environ pour traiter 4 200 000 Id.
    (test basé sur 100 000 * 10 call gludIDs[ 42 ids ])
    [ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
    Ma messagerie n'est pas la succursale du forum... merci!

  2. #42
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut
    Citation Envoyé par Dr.Who Voir le message
    Mais voila, tu dois juste fournir un tableau d'integer disctinct correspondant aux id.
    Et pourquoi je dis qu'il faut un champs Id_localite disctinct dans le client pour eviter de faire une fonction lourde "ungluIds->array of integer".
    Après rien n'empèche, mais j'ai peur qu'avec 100000 entrées ou plus, on mette plus de 10 secondes à générer et corriger les ids.

    gluIds mets 5 seconde (4437ms) environ pour traiter 4 200 000 Id.
    (test basé sur 100 000 * 10 call gludIDs[ 42 ids ])

    Bonjour à tous,

    @ Dr.Who: merci pour ton aide . Oui c'est très rapide.

    Tu sais, j'ai restructuré toutes les tables de la base de donnée et j'ai réécrit tout depuis le début.Cette application peut-être finalisée que si je trouve une solution à ce souci qui est de grouper les id à l'affichage et à l'impression .

    Il me reste qu'à corriger l'erreur dans la procédure de notre ami SergioMaster (d'ailleurs merci aussi à lui de me prêter de l'aide).

    @ Serge : à propos de cette erreur , dis-moi où il faut corriger stp? Car comme je t'ai dis, la procédure loupe le dernier chiffre de la suite de série si on cherche à filtrer la query une une seul localité, par contre elle fonctionne sans souci s'il n'y a pas de filtre.

    Merci.

    NABIL74

  3. #43
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut
    Bonsoir à tous,

    @ Serge:

    Tu sais quand je fais le tri sur une localité,elle fonctionne très bien.
    J'ai rien changé dans ta procédure.En fait, j'ai vidé la table Clients et j'ai insérer à nouveau les Id_Clients et là boom ça marche!

    Pendant presque une semaine que ça me tape sur les nerfs seulement pour un vidage de la table Clients !!!!



    Un énorme merci à vous de m'avoir prêter de l'aide.
    Je ne sais pas comment te remercier mon cher ami Serge.Mille fois MERCI et bravo.

    Si tu fais un jour un tour en Algérie, on pourrait faire ensemble une belle partie de pêche.

    Encore fois merci.

    Pour moi ce topic est résolu et dieu merci

    Nabil

  4. #44
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut Amélioration
    bonsoir,

    je me demandais si on pourrait améliorer ça en faisant un Count des Id_Client selon chaque localité parce qu'avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Query1.Active := False;
    Query1.SQL.Clear;
    Query1.SQL.Add('SELECT LOCALITE,NUMERO, Count(*)CountALL FROM CLIENTS  WHERE  Localite=:L');
    Query1.SQL.Add(' ORDER BY LOCALITE,NUMERO');
    Query1.ParambyName('L').asString:=DBEdit2.Text;
    Query1.Active:=True;
    ça ne marche pas le Count , il renvoit bien sûr '1' , par contre si on efface le NUMERO de la requête ça marche, on récupère le nombre des id de chaque localité mais dans notre cas, le Id_Client est la base de la requête.

    une idée?

    Merci

  5. #45
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Citation Envoyé par NABIL74 Voir le message
    ça ne marche pas le Count , il renvoit bien sûr '1' , par contre si on efface le NUMERO de la requête ça marche, on récupère le nombre des id de chaque localité mais dans notre cas, le Id_Client est la base de la requête.
    Count est une fonction d'agrégation comme min, max, avg et s'utilise généralement associé à une clause d’agrégation group by...
    Avec Firebird ou Ms SqlServer, on utiliserait une Expression de Table Commune ou CTE (c. Message de @SergioMaster). Avec Paradox, comme je l'ai indiqué au début , je ferais cela en 2 étapes via une table temporaire ou un clientdataset.
    Philippe.

  6. #46
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut
    Citation Envoyé par Ph. B. Voir le message
    Count est une fonction d'agrégation comme min, max, avg et s'utilise généralement associé à une clause d’agrégation group by...
    Avec Firebird ou Ms SqlServer, on utiliserait une Expression de Table Commune ou CTE (c. Message de @SergioMaster). Avec Paradox, comme je l'ai indiqué au début , je ferais cela en 2 étapes via une table temporaire ou un clientdataset.
    Oui Ph.B ,SergioMaster m'a déjà dit que sur Firebird, on pourrait faire ça en utilisant les requêtes récursives , mais avec Paradox, tu dis qu'il faut passer par deux étapes via une table temporaire ou un clientdataset.
    La table temporaire je l'ai, mais j'ignore si elle aura avec les mêmes champs ou non.
    La procédure de Serge me va bien , les enregistrements sont poster dans cette table temporaire et puis je les récupère pour imprimer mon état, par contre pour faire un Count des id là je ne sais pas comment m'y prendre, ça me dépasse un peu .

    A+

    Nabil

  7. #47
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Citation Envoyé par NABIL74 Voir le message
    La procédure de Serge me va bien , les enregistrements sont poster dans cette table temporaire et puis je les récupère pour imprimer mon état, par contre pour faire un Count des id là je ne sais pas comment m'y prendre, ça me dépasse un peu .
    Pour compter, une solution est de le faire lors de la recherche des ID !
    Je reprends le code que j'avais écrit pour la recherche des intervalles et je vais modifier 4 lignes :
    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    // Recherche des intervalles et comptage des éléments de chaque intervalle
    procedure TForm1.BtnIntervallesClick(Sender: TObject);
    var
      Deb,
      Fin,
      Courant: Integer;
    begin
      ListeSequence.Clear;
     
      QEntete.Active := False;
      QEntete.SQL.Clear;
      QEntete.SQL.Add('SELECT DISTINCT(NUMERO) FROM FACTURES WHERE ANNEE = ' + QuotedStr(CodeSaison.Text));
      QEntete.SQL.Add('ORDER BY NUMERO');
      QEntete.Active := True;
     
      with QEntete do
      begin
        DisableControls;
        try
          First;
          Deb := MaxInt;
          Courant := MaxInt;
          while not EOF do
          begin
            Fin := FieldByName('NUMERO').AsInteger;
            if Deb > Fin then
            begin
              Deb := Fin
            end
            else
            begin
              if Courant + 1 < Fin then
              begin
                if Deb = Courant then
                  //ListeSequence.Items.Add(IntToStr(Deb))
                  ListeSequence.Items.Add(IntToStr(Deb)
                    + ' [1]') // <=> Count = 1
                else
                  //ListeSequence.Items.Add(IntToStr(Deb) + '..' + IntToStr(Courant));
                  ListeSequence.Items.Add(IntToStr(Deb) + '..' + IntToStr(Courant)
                    + ' [' +  IntToStr(Courant - Deb + 1) + ']');  // <=> Count = Courant - Deb + 1
                Deb := Fin;
              end;
            end;
            Courant := Fin;
            Next;
          end;
        finally
          if Deb = Courant then
            //ListeSequence.Items.Add(IntToStr(Deb))
            ListeSequence.Items.Add(IntToStr(Deb)
              + ' [1]')  // <=> Count = 1
          else
            //ListeSequence.Items.Add(IntToStr(Deb) + '..' + IntToStr(Courant));
            ListeSequence.Items.Add(IntToStr(Deb) + '..' + IntToStr(Courant)
              + ' [' +  IntToStr(Courant - Deb + 1) + ']');  // <=> Count = Courant - Deb + 1
     
          EnableControls;
        end;
      end;
      QEntete.Active := False;
      if ListeSequence.Items.Count > 0 then
        ListeSequence.Visible := True;
    end;
    Reste à l'adapter à ce que vous avez repris du code de @SergioMaster .
    Philippe.

  8. #48
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut
    Bonsoir,

    @ Ph.B : merci pour ton aide

    Voilà ce que j'ai fait avec la procédure de Serge:

    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
    case t of
         0 : begin
             if Length(Lignememo)=0
                 then LigneMemo:=Inttostr(WNum)
                 else LigneMemo:=Lignememo+','+Inttostr(WNum) ;
             snum:=wnum;
             end;
         1 : Wnum:=Query1NUMERO.asInteger;
         -1 : if snum<>wnum then lignememo:=Lignememo+'...'+Inttostr(wnum)  +  ' [' +  IntToStr(wNum - sNum + 1) + ']'
         else begin
               if snum=wnum then Lignememo:=Lignememo+', '
               else Lignememo:=Lignememo+'...'+inttostr(wnum)  +  ' [' +  IntToStr(wNum - sNum + 1) + ']' +', ');
                wNum:=Query1NUMERO.asInteger;
                sNum:=Query1NUMERO.asInteger;
                Lignememo:=Lignememo+Inttostr(WNum);
              end;
         end;
        end;
    Elle n'est pas ok à 100%,je t'explique: s'il s'agit d'une suite de série, c'est ok, ex affichage:
    100-120 [21]

    mais s'il s'agit d'un seul chiffre, là pas de count ,ex affichage:
    150 => rien.

    Ecoute, y a t-il pas une solution pour poster ce count dans un champ de la Table temporaire ?

    Merci

    A+

    NAbil

  9. #49
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 017
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 017
    Points : 40 931
    Points
    40 931
    Billets dans le blog
    62
    Par défaut
    Franchement l'effort n'était pas bien gros pour rajouter le nombre . Il me semble en plus que Ta modification apportée a amener une erreur grossière !
    le Else après le -1 est un else de Case , pas du if snum<>wnum

    Je ne crois pas que tu ais bien saisi comment fonctionne cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
       // EOF  
       -1 : if snum<>wnum then lignememo:=Lignememo+'...'+Inttostr(wnum)  +  ' [' +  IntToStr(wNum - sNum + 1) + ']'
             else LigneMemo:=LigneMemo+' [1]';
        // Autres valeurs de T 
         else begin
               if snum=wnum then Lignememo:=Lignememo+' [1], '
               else Lignememo:=Lignememo+'...'+inttostr(wnum)  +  ' [' +  IntToStr(wNum - sNum + 1) + ']' +', ');
    P.S. Correction faite le matin , avant mon café => cerveau encore embrumé et non testée

    remarque pour la dernière ligne IntToStr(wnum-snum+1) aurait pu être remplacé par T+1 ce que tu n'as même pas remarqué , cependant pour la lisibilité entre le cas T>1 et EOF il vaut mieux laisser tel quel


    et non , on ne peut pas utiliser la fonction d'agrégat COUNT et la stocker dans la table temporaire tout simplement parce que tu ne connais pas le nombre de "suite" donc le nombre de champs "nombre" qu'il te faudrait à moins de faire un enregistrement par "suite"
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  10. #50
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Franchement l'effort n'était pas bien gros pour rajouter le nombre . Il me semble en plus que Ta modification apportée a amener une erreur grossière !
    Bonjour,

    @ Serge:

    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
    case t of
         0 : begin
             if Length(Lignememo)=0
                 then LigneMemo:=Inttostr(WNum)
                 else LigneMemo:=Lignememo+','+Inttostr(WNum) ;
             snum:=wnum;
             end;
     
          1 : Wnum:=Query1Num_Objet.asInteger ;
     
         -1 : if snum<>wnum then lignememo:= Lignememo+'-'+Inttostr(wnum)+  ' [' +  IntToStr(wNum - sNum + 1) + ']'
     
              else LigneMemo:=LigneMemo+' [1]';
         else begin
              if snum=wnum then Lignememo:=Lignememo+' [1], '
               else Lignememo:=(Lignememo+'-'+inttostr(wnum) +  ' [' +  IntToStr(wNum - sNum + 1) + ']' +', '); 
                wNum:=Query1Num_Objet.asInteger;
                sNum:=Query1Num_Objet.asInteger;
                Lignememo:=(Lignememo + Inttostr(WNum));
              end;
         end;
        end;
    Voilà ce que ça donne:

    Nantes,2704 // pas de [1] ??
    Bordeaux,2071 // pas de [1] ??
    Montpellier,2653 // pas de [1]
    Paris,1 [1], 61-65 [5], 100-120 [21], 200-210 [11], 240-250 [11], 3060 //ici pour 3060, pas de [1] ??
    Cannes,2603 [1] // par contre ici c'est ok [1]


    Citation Envoyé par SergioMaster Voir le message
    remarque pour la dernière ligne IntToStr(wnum-snum+1) aurait pu être remplacé par T+1 ce que tu n'as même pas remarqué , cependant pour la lisibilité entre le cas T>1 et EOF il vaut mieux laisser tel quel
    Non, j'ai bien remarqué mais il renvoit un compte qui n'est pas bon.Voilà ce que j'ai obtenu avec le T+1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     if snum=wnum then Lignememo:=Lignememo+' [1], '
               else Lignememo:=(Lignememo+'-'+inttostr(wnum) +  ' [' +  IntToStr(T + 1) + ']' +', '); //**
    résultat:

    Nantes,2704
    Bordeaux,2071
    Montpellier,2653
    Paris,1 [1], 61-65 [36], 100-120 [81], 200-210 [31], 240-250 [2811], 3060
    Cannes,2603 [1]

    Serge, ne crois-tu pas que si on groupait les id de toute la localité , c'est mieux non?
    ex:
    Paris,1 [1], 61-65 [5], 100-120 [21], 200-210 [11], 240-250 [11], 3060
    => Paris= 1 + 5 +21 + 11 + 11 + 1 = 50

    Paris= 50 c'est ça qui est mieux.

    Pour poster le 50 dans la table temporaire, une idée?

    Merci

    A+

    Nabil

  11. #51
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Citation Envoyé par NABIL74 Voir le message
    Voilà ce que ça donne:

    Nantes,2704 // pas de [1] ??
    Bordeaux,2071 // pas de [1] ??
    Montpellier,2653 // pas de [1]
    Paris,1 [1], 61-65 [5], 100-120 [21], 200-210 [11], 240-250 [11], 3060 //ici pour 3060, pas de [1] ??
    Cannes,2603 [1] // par contre ici c'est ok [1]
    AMHA, il manque un test en sortie d'une boucle intermédiaire de votre code, d'où l'absence de compteur en fin de chaque regroupement de localité, sauf la dernière qui doit être traitée par la boucle principale.
    Citation Envoyé par NABIL74 Voir le message
    Serge, ne crois-tu pas que si on groupait les id de toute la localité , c'est mieux non?
    ex:
    Paris,1 [1], 61-65 [5], 100-120 [21], 200-210 [11], 240-250 [11], 3060
    => Paris= 1 + 5 +21 + 11 + 11 + 1 = 50

    Paris= 50 c'est ça qui est mieux.

    Pour poster le 50 dans la table temporaire, une idée?
    Il suffit en partant de la boucle de comptage de séquence de rajouter une variable de cumul initialisée à 0 pour chaque nouvelle localité et qui est incrémentée de 1 ou de wNum - sNum + 1. cette info viendra remplacer les cumuls par séquence...
    Philippe.

  12. #52
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut
    Citation Envoyé par Ph. B. Voir le message
    AMHA, il manque un test en sortie d'une boucle intermédiaire de votre code, d'où l'absence de compteur en fin de chaque regroupement de localité, sauf la dernière qui doit être traitée par la boucle principale.
    C'est fort possible qu'il manque un test en sortie d'une boucle intermédiaire du code.


    Citation Envoyé par Ph. B. Voir le message
    Il suffit en partant de la boucle de comptage de séquence de rajouter une variable de cumul initialisée à 0 pour chaque nouvelle localité et qui est incrémentée de 1 ou de wNum - sNum + 1. cette info viendra remplacer les cumuls par séquence...
    Franchement, dès le début ça était compliqué pour moi de grouper la suite de série de chiffres des id, et maintenant, pour compter le nombre des id de chaque localité c'est encore plus compliqué !

    C'est vrai que dans cette application, j'ai un peu mélangé les pinceaux





    Nabil

  13. #53
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 784
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 784
    Points : 5 915
    Points
    5 915
    Par défaut
    Citation Envoyé par NABIL74 Voir le message
    Franchement, dès le début ça était compliqué pour moi de grouper la suite de série de chiffres des id, et maintenant, pour compter le nombre des id de chaque localité c'est encore plus compliqué !
    Je pense surtout que vous vous faites une montagne d'un petit faux plat !
    Donc, à partir de mon précédent postulat
    Il suffit en partant de la boucle de comptage de séquence de rajouter une variable de cumul initialisée à 0 pour chaque nouvelle localité et qui est incrémentée de 1 ou de wNum - sNum + 1. cette info viendra remplacer les cumuls par séquence...
    et en adaptant mon code, j'obtiens :
    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    // Recherche des intervalles et comptage des éléments de chaque intervalle et cumul général
    procedure TForm1.BtnIntervallesClick(Sender: TObject);
    var
      Deb,
      Fin,
      Courant,
      Cumul: Integer;
    begin
      ListeSequence.Clear;
     
      QEntete.Active := False;
      QEntete.SQL.Clear;
      QEntete.SQL.Add('SELECT DISTINCT(NUMERO) FROM FACTURES WHERE ANNEE = ' + QuotedStr(CodeSaison.Text));
      QEntete.SQL.Add('ORDER BY NUMERO');
      QEntete.Active := True;
      Cumul := 0;
     
      with QEntete do
      begin
        DisableControls;
        try
          First;
          Deb := MaxInt;
          Courant := MaxInt;
          while not EOF do
          begin
            Fin := FieldByName('NUMERO').AsInteger;
            if Deb > Fin then
            begin
              Deb := Fin
            end
            else
            begin
              if Courant + 1 < Fin then
              begin
                if Deb = Courant then
                begin
                  //ListeSequence.Items.Add(IntToStr(Deb))
                  ListeSequence.Items.Add(IntToStr(Deb)
                    + ' [1]'); // <=> Count = 1
                  Cumul := Cumul + 1;
                end
                else
                begin
                  //ListeSequence.Items.Add(IntToStr(Deb) + '..' + IntToStr(Courant));
                  ListeSequence.Items.Add(IntToStr(Deb) + '..' + IntToStr(Courant)
                    + ' [' +  IntToStr(Courant - Deb + 1) + ']');  // <=> Count = Courant - Deb + 1
                  Cumul := Cumul + Courant - Deb + 1;
                end;
                Deb := Fin;
              end;
            end;
            Courant := Fin;
            Next;
          end;
        finally
          if Deb = Courant then
          begin
            //ListeSequence.Items.Add(IntToStr(Deb))
            ListeSequence.Items.Add(IntToStr(Deb)
              + ' [1]');  // <=> Count = 1
            Cumul := Cumul + 1;
          end
          else
          begin
            //ListeSequence.Items.Add(IntToStr(Deb) + '..' + IntToStr(Courant));
            ListeSequence.Items.Add(IntToStr(Deb) + '..' + IntToStr(Courant)
              + ' [' +  IntToStr(Courant - Deb + 1) + ']');  // <=> Count = Courant - Deb + 1
            Cumul := Cumul + Courant - Deb + 1;
          end;
          // Rajout du cumul en fin de liste
          ListeSequence.Items.Add('Cumul = ' + InToStr(Cumul);
     
          EnableControls;
        end;
      end;
      QEntete.Active := False;
      //if ListeSequence.Items.Count > 0 then
      ListeSequence.Visible := True;
    end;
    Et le tour est joué !
    Philippe.

  14. #54
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut
    Merci beacoup Phillipe pour ton aide.

    impécable !

    Pour info, c'est une application que je développe pour un ami à moi (gratuitement) qui possède une société de vente.
    Alors, il m'a demandé de lui codé une.

    Je n'ai pas eu trop de difficulter à le faire, sauf pour le groupage des ID, là je me suis arraché les cheveux

    Il a des clients dans pas mal de villes d'Algérie. Alors, il arrive des fois que dans une ville comme Alger, il y a plusieurs clients dans chaque arrondissements.

    Il m'a dis de faire aussi le groupage des ID suivant la Localité et Arrondissement(ou par Cité)


    Pardon pour ce changement de situation de dernière minute, après beaucoup d'efforts !

    là, comment on peut adapter le code?

    Rappellons que l'objectif maintenant est :

    - Grouper les ID selon : la Localité et Arrondissement(ou Cité).

    - Et de le faire comme ça :

    Nantes, 2704, Arrondissement13 =1
    Bordeaux,2071 , Arrondissement1 =1
    Montpellier,2653 , Arrondissement19 =15
    Paris,1-15, Arrondissement18 = 16 , 61-65 Arrondissement17 = 5
    Cannes,2603 ,Arrondissement12 =1


    Encore une fois Pardon les copains

  15. #55
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 017
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 017
    Points : 40 931
    Points
    40 931
    Billets dans le blog
    62
    Par défaut
    , ben moi j'abandonne , un cahier des charges qui change sans arrêt, une utilisation de techno obsolète , c'en est trop !

    pour conclure , voici une requête FIREBIRD qui fournirai les informations (j'y ai même inclus les districts)
    sans passer par procedures , uniquement des Common Table Expression et encore , je suis sur que c'est largement perfectible en utilisant la récursivité

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE TABLE TCLI
    (
      NUM Integer NOT NULL,
      LOCALITE Varchar(20) NOT NULL,
      DISTRICT Varchar(20) NOT NULL,
     
      CONSTRAINT PK_TCLI PRIMARY KEY (NUM)
    );

    Code SQL JEU d'essai : 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
     
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('1', 'PARIS', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('2', 'PARIS', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('3', 'PARIS', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('4', 'PARIS', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('5', 'NANTES', 'A');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('6', 'NANTES', 'A');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('7', 'PARIS', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('8', 'NANTES', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('10', 'PARIS', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('20', 'NANTES', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('21', 'NANTES', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('22', 'NANTES', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('30', 'NANTES', 'B');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('31', 'NANTES', 'A');
    INSERT INTO TCLI (NUM, LOCALITE, DISTRICT) VALUES ('32', 'NANTES', 'A');
    Code SQL : 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
     
    WITH 
    --DEBUT DE SERIE
    DT AS (
    SELECT  LOCALITE,DISTRICT,NUM
    FROM    TCLI t
    WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    TCLI r 
            WHERE   LOCALITE=T.LOCALITE AND DISTRICT=T.DISTRICT AND r.NUM = t.NUM -1
     
            )
    ),
    --FIN DE SERIE
    NT AS (
    SELECT  LOCALITE,DISTRICT,NUM
    FROM    TCLI t
    WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    TCLI r 
            WHERE   LOCALITE=T.LOCALITE AND DISTRICT=T.DISTRICT AND r.NUM = t.NUM +1
     
            )
    )
     
     
    SELECT LOCALITE,DISTRICT,NUM AS DEBUT,(SELECT FIRST 1 NUM FROM NT WHERE NUM>=DT.NUM) AS FIN,
           (SELECT FIRST 1 NUM FROM NT WHERE NUM>=DT.NUM)-NUM+1 AS NB 
    FROM DT
    ORDER BY 1,2,3

    Citation Envoyé par Resultat
    NANTES A 5 6 2
    NANTES A 31 32 2
    NANTES B 8 8 1
    NANTES B 20 22 3
    NANTES B 30 30 1
    PARIS B 1 4 4
    PARIS B 7 7 1
    PARIS B 10 10 1
    [edit]
    en 'affinant' on arrive même a obtenir ceci
    NANTES A 5 ..6,31 ..32 4
    NANTES B 30 ,8 ,20 ..22 5
    PARIS B 7 ,10 ,1 ..4 6
    Dommage que la fonction d'aggrégat LIST , n'ordonne pas (du moins en FB 2.1) ;-)
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  16. #56
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    , ben moi j'abandonne , un cahier des charges qui change sans arrêt, une utilisation de techno obsolète , c'en est trop !

    pour conclure , voici une requête FIREBIRD qui fournirai les informations (j'y ai même inclus les districts)
    sans passer par procedures , uniquement des Common Table Expression et encore , je suis sur que c'est largement perfectible en utilisant la récursivité
    @ Serge : vraiment désolé pour le changement du cahier de charge .

    et un grand Merci pour ta procédure de regroupement

    Merci pour la requête récursive sur Firebird.

    @ Phillipe : un grand Merci à toi aussi pour ta procédure de regroupement

  17. #57
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 017
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 017
    Points : 40 931
    Points
    40 931
    Billets dans le blog
    62
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT LOCALITE||' '||DISTRICT AS LOCALITE,NUMERO FROM CLIENTS ORDER BY LOCALITE,DISTRICT,NUMERO
    sans changer une ligne de code cela pourrait fonctionner
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  18. #58
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT LOCALITE||' '||DISTRICT AS LOCALITE,NUMERO FROM CLIENTS ORDER BY LOCALITE,DISTRICT,NUMERO
    sans changer une ligne de code cela pourrait fonctionner
    Bonjour,
    Merci pour ta réponse Serge, je l'ai testé hier comme tu me l'as dit, ça ajoute seulement LOCALITE et DISTRICT une après l'autre: Paris, District18.

    Sur Paradox le ||' '|| => ||', '||

    Et pour la suite de série, même résultat qu'avant, pas de changement.

    si c'est possible d'obtenir ça , ça série la fin de notre galère :

    Nantes, 2704, Arrondissement13 =1
    Bordeaux,2071 , Arrondissement1 =1
    Montpellier,2653 , Arrondissement19 =15
    Paris,1-15, Arrondissement18 = 16 , 61-65 Arrondissement17 = 5
    Cannes,2603 ,Arrondissement12 =1.

    Merci

Discussions similaires

  1. Problème requête SELECT condition WHERE string
    Par Glherbier dans le forum VBA Access
    Réponses: 3
    Dernier message: 27/10/2010, 19h43
  2. SQL Problème requête SELECT
    Par Seth_75 dans le forum Développement
    Réponses: 2
    Dernier message: 30/03/2009, 16h02
  3. Problème requête SELECT ORACLE
    Par vizlebiz dans le forum Langage SQL
    Réponses: 4
    Dernier message: 28/02/2008, 17h20
  4. Problème Requête SELECT sur champ texte
    Par arnaud_verlaine dans le forum WinDev
    Réponses: 5
    Dernier message: 02/10/2007, 22h19
  5. [SQL] Problème requête SELECT
    Par dolf13 dans le forum PHP & Base de données
    Réponses: 21
    Dernier message: 05/07/2006, 00h54

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